我正在用TS, yarn工作空间构建Next.js单线程项目。
例如,我在yarn工作区中有两个包,/web
和/api
。/web
是next.js项目,/api
是/web
使用的共享子包。
/my-project <-- project root
package.json
/web
src/
package.json
tsconfig.json
next.config.js
/api
src/ <-- rootDir
dist/ <-- outDir
package.json
tsconfig.json
...
// /my-project/package.json
{
"private": true,
"workspaces": [
"web",
"api"
],
}
// /web/packcage.json
{
"dependencies": {
"@api": "workspace:*"
}
}
// /api/packcage.json
{
"name": "@api"
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
}
// /api/tsconfing.json
{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"module": "ES6",
"moduleResolution": "node",
"target": "ES6",
},
}
从/api
的tsconfig中,TS创建了具有es6模块系统的编译结果。("module": "ES6"
)
由于nextjs不支持用ES模块构建的外部包,我预计/api
包在/web
项目中不起作用。但是,它运行得很好。
为什么这是可能的?
当我尝试使用一些使用ES模块的包(仅为浏览器构建)时,我遇到了一些错误,如unexpected token: export
。那时,我必须翻译它们手动使用next-transpile-modules
,然后它解决了这个问题。但是,在这种情况下,nextjs与es模块包一起工作没有任何问题。我是不是误解了什么?
NextJs 11.1+有一个实验性的选项来支持esm。反馈线程在这里。
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
experimental: {
// Prefer loading of ES Modules over CommonJS
// @link {https://nextjs.org/blog/next-11-1#es-modules-support|Blog 11.1.0}
// @link {https://github.com/vercel/next.js/discussions/27876|Discussion}
esmExternals: true,
// Experimental monorepo support
// @link {https://github.com/vercel/next.js/pull/22867|Original PR}
// @link {https://github.com/vercel/next.js/discussions/26420|Discussion}
externalDir: true,
}
}
export default nextConfig;
ESM通常需要的不仅仅是"模块"; "es6"在配置…但是正如你注意到的,我意识到一些esm包,比如"@sindrehorsus",在没有实验标志的情况下工作。
也就是说,将experimental.esmExternals设置为true将解决大多数边缘情况,并且应该使next-transpile-modules过时。
请注意,通常我倾向于设置"模块";esnext"而不是&;es6&;
PS:如果它有帮助,你可以看看这个评论:https://stackoverflow.com/a/69554480/5490184或https://github.com/belgattitude/nextjs-monorepo-example。