You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Yarn Workspace依赖提升本地正常,部署环境失效排查

问题:Yarn Workspace依赖提升在Vercel部署时失效,导致运行时「模块未找到」

我使用Next.js服务端渲染,本地运行Yarn Workspace时,根目录package.json中定义的lodash-es包可被子目录正常引用。但通过Cloud Build部署到Vercel后,运行时出现「模块未找到」错误——子目录package.json中未声明该包,推测是Workspace依赖提升未生效。

项目结构

.
└── tiles/
    ├── packages/
    │   ├── hosted/
    │   │   ├── next.config.js
    │   │   ├── tailwind.config.js
    │   │   ├── package.json
    │   │   ├── tsconfig.json
    │   │   ├── node_modules (auto-generated)
    │   │   ├── .next (auto-generated)
    │   │   └── .vercel (auto-generated)
    │   ├── modules/
    │   │   ├── tsconfig.json
    │   │   ├── package.json
    │   │   └── node_modules (auto-generated)
    │   └── react/
    │       ├── tsconfig.json
    │       ├── package.json
    │       └── node_modules (auto-generated)
    ├── .yarnrc.yml
    ├── package.json
    └── yarn.lock

子包依赖配置

hosted/package.json中的Workspace依赖:

{
  "dependencies": {
    "@project/modules": "workspace:*",
    "@project/react": "workspace:*"
  }
}

本地运行命令

tiles根目录执行:

cd packages/react && yarn && tsc && cd packages/modules && yarn && yarn build && concurrently --kill-others "cd packages/react && yarn tsc --watch" "cd packages/modules && yarn tsc --watch"  "cd packages/hosted && NODE_OPTIONS='--inspect' next dev -p 3001"

Cloud Build部署配置(原配置)

steps:
  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "build-react"
    dir: "javascript/tiles/packages/react"
    entrypoint: "bash"
    args:
      - "-c"
      - |-
        yarn gcp-auth refresh \
        && yarn install \
        && git diff --exit-code \
        && yarn run build

  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "build-modules"
    dir: "javascript/tiles/packages/modules"
    entrypoint: "bash"
    args:
      - "-c"
      - |-
        yarn gcp-auth refresh \
        && yarn install \
        && git diff --exit-code \
        && yarn run build

  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "build-and-deploy"
    dir: "javascript/tiles/packages/hosted"
    entrypoint: "bash"
    env:
      - "COMMIT_SHA=$COMMIT_SHA"
    args:
      - "-c"
      - |-
        yarn gcp-auth refresh \
        && yarn install \
        && git diff --exit-code \
        && yarn vercel --token "$$VERCEL_ACCESS_TOKEN" --scope <vercel_project> pull --yes \
        && yarn vercel --token "$$VERCEL_ACCESS_TOKEN" --scope <vercel_project> build --prod \
        && find .vercel/output/static/_next/static -type f -name "*.map" -delete \
        && yarn vercel --token "$$VERCEL_ACCESS_TOKEN" --scope <vercel_project> --yes deploy --prebuilt --prod

根目录.yarnrc.yml配置

nodeLinker: node-modules
nmHoistingLimits: workspaces

npmScopes:
  fermat:
    npmAlwaysAuth: true
    npmPublishRegistry: "https://us-central1-npm.pkg.dev/<project-name>/npm-repository/"
    npmRegistryServer: "https://us-central1-npm.pkg.dev/<project-name>/npm-repository/"

unsafeHttpWhitelist:
  - metadata.google.internal

plugins:
  - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
    spec: "@yarnpkg/plugin-interactive-tools"
  - path: .yarn/plugins/@yarnpkg/plugin-gcp-auth.cjs
    spec: "https://github.com/AndyClausen/yarn-plugin-gcp-auth/releases/latest/download/plugin-gcp-auth.js"

yarnPath: .yarn/releases/yarn-3.3.0.cjs

Vercel端已启用「在构建步骤中包含根目录外的文件」选项。


问题根源

Cloud Build的每个步骤都进入子目录单独执行yarn install,而非从Workspace根目录操作。Yarn的依赖提升是基于根目录统一管理的node_modules,子目录单独执行install只会安装该子包的直接依赖和Workspace依赖,无法继承根目录声明的公共依赖(如lodash-es)。

解决方案

调整Cloud Build配置,统一从Workspace根目录执行yarn install,再分别运行子包的构建命令:

修正后的Cloud Build配置

steps:
  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "root-install"
    dir: "javascript/tiles"
    entrypoint: "bash"
    args:
      - "-c"
      - |-
        yarn gcp-auth refresh \
        && yarn install \
        && git diff --exit-code

  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "build-react"
    dir: "javascript/tiles"
    entrypoint: "bash"
    args:
      - "-c"
      - |-
        yarn workspace @project/react build

  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "build-modules"
    dir: "javascript/tiles"
    entrypoint: "bash"
    args:
      - "-c"
      - |-
        yarn workspace @project/modules build

  - name: "us-central1-docker.pkg.dev/<project-name>/docker-repository/builders/node-with-utils"
    id: "build-and-deploy"
    dir: "javascript/tiles/packages/hosted"
    entrypoint: "bash"
    env:
      - "COMMIT_SHA=$COMMIT_SHA"
    args:
      - "-c"
      - |-
        yarn vercel --token "$$VERCEL_ACCESS_TOKEN" --scope <vercel_project> pull --yes \
        && yarn vercel --token "$$VERCEL_ACCESS_TOKEN" --scope <vercel_project> build --prod \
        && find .vercel/output/static/_next/static -type f -name "*.map" -delete \
        && yarn vercel --token "$$VERCEL_ACCESS_TOKEN" --scope <vercel_project> --yes deploy --prebuilt --prod

额外注意事项

  1. 确保根目录package.json中的lodash-es放在dependencies下,而非devDependencies——Next.js SSR需要运行时依赖可被访问。
  2. 确认Vercel的「包含根目录外文件」选项保持启用,保证Workspace相关配置能被正确读取。

内容的提问来源于stack exchange,提问作者10may

火山引擎 最新活动