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/dbpackage.jsonmain 指向的文件是真实存在的。 你的配置:"main": "./dist/index.js"。 确保运行 pnpm build 后,packages/db/dist/index.js 是存在的。

第五步:重新构建与部署

  1. 在根目录运行:
    pnpm run build
  2. 检查生成的 apps/api/dist/main.js。如果你搜索文件内容,应该能看到 @workspace/db 里的代码被直接写在这个文件里了,而不是 require('@workspace/db')

为什么这样做能解决问题?

  1. 之前的情况: API 运行 require('@workspace/db') -> Node 去 /var/task/node_modules/@workspace/db 找 -> Serverless 环境通常这里是个软链接或者被修剪掉了 -> 报错

  2. 现在的做法 (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) 是最安全的方式。