monorepo 部署 vercel NestJs 找不到共享包
这是一个典型的 NestJS + Monorepo + Serverless (Vercel/Lambda) 部署问题。
问题核心在于:默认的 nest build 只是把 TS 转译成 JS,保留了 require('@workspace/db')。在部署环境(/var/task/)中,包管理器创建的软链接(Symlinks)通常会丢失,或者 node_modules 被修剪,导致运行时找不到这个本地包。
最稳健的解决方案是: 告诉 NestJS 在构建时,将 @workspace/db 的代码打包(Bundle)进 API 的文件中,而不是在运行时去 node_modules 找。
你需要按以下步骤操作(即使你现在没有 webpack 文件,我们需要创建一个):
第一步:安装 Webpack 相关依赖
在 apps/api 目录下安装以下开发依赖。NestJS 的构建底层支持 Webpack,但需要这些插件来处理排除项。
# 在 apps/api 目录下运行
pnpm add -D webpack webpack-node-externals
第二步:创建 Webpack 配置文件
在 apps/api 根目录下(和 package.json 同级),新建文件 webpack.config.js:
const nodeExternals = require('webpack-node-externals');
module.exports = function (options, webpack) {
return {
...options,
externals: [
nodeExternals({
// 关键配置:允许 @workspace/db 被打包进 main.js
// 这样运行时就不需要去 node_modules 找它了
allowlist: ['@workspace/db'],
}),
],
};
};
第三步:修改 Nest CLI 配置
修改 apps/api/nest-cli.json,告诉 Nest 使用 Webpack 构建,并使用我们刚才创建的配置。
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true,
"webpack": true,
"webpackConfigPath": "webpack.config.js"
}
}
第四步:确保构建顺序 (Turbo)
你的 turbo.json 配置看起来是正确的:
"build": {
"dependsOn": ["^build"],
...
}
这意味着当你运行 pnpm build 时,Turbo 会先构建 @workspace/db (生成 dist 目录),然后再构建 apps/api。
重要检查:
确保你的 @workspace/db 的 package.json 中 main 指向的文件是真实存在的。
你的配置:"main": "./dist/index.js"。
确保运行 pnpm build 后,packages/db/dist/index.js 是存在的。
第五步:重新构建与部署
- 在根目录运行:
pnpm run build - 检查生成的
apps/api/dist/main.js。如果你搜索文件内容,应该能看到@workspace/db里的代码被直接写在这个文件里了,而不是require('@workspace/db')。
为什么这样做能解决问题?
-
之前的情况: API 运行
require('@workspace/db')-> Node 去/var/task/node_modules/@workspace/db找 -> Serverless 环境通常这里是个软链接或者被修剪掉了 -> 报错。 -
现在的做法 (Allowlist): Webpack 发现代码引用了
@workspace/db-> 它是白名单成员 -> Webpack 去读取db包的dist/index.js源码 -> 把源码直接复制粘贴到api/dist/main.js中 -> 运行时不再依赖外部文件。
补充:关于 path mapping (tsconfig)
如果上述步骤做完后,本地开发(dev)报错,请确保 apps/api/tsconfig.json 里没有错误的 paths 映射。通常在 Monorepo 中,如果不使用 Webpack 打包,需要在 tsconfig.json 里加上:
// apps/api/tsconfig.json
{
"compilerOptions": {
"paths": {
"@workspace/db": ["../../packages/db/src/index.ts"] // 指向源码
}
}
}
但在生产环境部署时,打包(Webpack Allowlist) 是最安全的方式。