本文记录一次典型的「本地好好的,合并进发版分支后 CI 挂掉」问题:根因是 pnpm 大版本升级带来的依赖构建脚本策略变化 ,以及 v11 配置位置迁移 。文末附 v10 → v11 迁移要点与官方链接。
一、现象是什么样的
我们的流程是:代码合并到指定分支(例如 dev / test)后,GitLab CI/CD 自动执行脚本构建并发版。脚本中有一段代码会下载最新的pnpm到服务器上,这就导致了本地分支是旧版,服务器是新版,会有不兼容的问题。
某次合并之后,流水线在 安装依赖 阶段失败,终端里出现类似报错:
text
[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild@0.25.5
Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.
有时还会在同一套流程里看到其它依赖(例如 vue-demi)也被列为 Ignored build scripts。
特点可以概括为:
- 触发点 往往是「新环境 / 新镜像 / 全局装的最新 pnpm」第一次执行
pnpm install。 - 报错发生在
pnpm install结束前后 ,尚未到业务vite build。 - 本地若仍使用旧版 pnpm 或未开启同等严格策略,不一定能第一时间复现,容易误判为「合并代码写坏了」。
于是怀疑是pnpm发布了新的版本导致旧的格式不兼容。去github上看了一下,果然如此。昨天偷偷发布了v11版本导致我今天发版失败。(作为还在实习的大学生第一次遇见这种情况,要是没有AI我还真不知道是版本问题)
二、真正的原因是什么
pnpm v11:配置从 package.json#pnpm 迁到 pnpm-workspace.yaml
pnpm v11 有一类 breaking change:大量原先写在 package.json 的 pnpm 字段里的配置,需要迁到仓库根目录的 pnpm-workspace.yaml(官方迁移文档有说明)。
如果仓库里只有 package.json 里的 onlyBuiltDependencies / patchedDependencies,而 Runner 上实际按 v11 解析,可能出现:
- 构建脚本允许列表 未按预期生效 → 继续触发
IGNORED_BUILDS; - **补丁(patchedDependencies)**未按预期应用 →
pnpm-lock.yaml里补丁相关段落与依赖解析不一致,甚至表现为「lockfile 里 patch 信息像被删掉」。
因此:表面上是 esbuild 报错,实质是「pnpm 大版本 + 新安全模型 + 配置未迁移」叠加。
三、如何从 pnpm v10 迁移到 v11(实践清单)
下列步骤对应官方迁移思路,适合在升级 major 时按顺序做。
1. 阅读官方迁移说明
先通读 v10 → v11 的 breaking changes,避免只改一两处配置却漏掉全局行为变化。
2. 使用官方 codemod(推荐)
以下命令以 pnpm 官方文档为准 (中英文页面一致,中文见 Migrating from v10 to v11(简体中文))。
在项目根目录执行:
bash
cd /path/to/your/project
pnpx codemod run pnpm-v10-to-v11
或使用全局安装的 codemod:
bash
pnpm add --global codemod
codemod run pnpm-v10-to-v11
3.自动迁移的内容(codemod 会自动完成)
- 将
package.json#pnpm中的配置迁移到pnpm-workspace.yaml中; - 将
.npmrc拆分为"认证/registry 配置"和"其他配置"两部分; - 把
onlyBuiltDependencies、neverBuiltDependencies、ignoredBuiltDependencies、onlyBuiltDependenciesFile合并为一个单一的allowBuilds映射; - 将
managePackageManagerVersions、packageManagerStrict、packageManagerStrictVersion合并为新的pmOnFail配置; - 重命名配置项:
allowNonAppliedPatches→allowUnusedPatchesauditConfig.ignoreCves→auditConfig.ignoreGhsas
- 将
useNodeVersion转换为根package.json中的devEngines.runtime配置; - 将
package.json中的packageManager更新为目标 pnpm v11 版本。
4.手动收尾的内容(需要人工处理)
-
CVE → GHSA
auditConfig.ignoreCves已改名为auditConfig.ignoreGhsas;- 但每个
CVE-YYYY-NNNNN仍需手动替换为对应的GHSA-xxxx-xxxx-xxxx; - 对应的 GHSA ID 可在
pnpm audit输出的 "More info" 列中查看。
-
ignorePatchFailures已移除- 失败的 patch 现在会直接抛错;
- 需要修复 patch 内容,或者移除该依赖。
-
工作区子包中的
executionEnv.nodeVersion已移除- 需要在该子包自己的
devEngines.runtime中声明运行时版本。
- 需要在该子包自己的
-
npm_config_*环境变量不再被读取- 需要将它们改为
pnpm_config_*; - 例如在 CI 配置、shell profile、Docker 镜像中都要同步修改。
- 需要将它们改为
-
pnpm link <pkg-name>的解析方式变更- 不再从全局 store 中解析包;
- 应改为使用相对路径或绝对路径,例如:
pnpm link ./foo。
-
pnpm install -g(不带参数)不再支持- 应改用:
pnpm add -g <pkg>。
- 应改用:
-
pnpm server已被移除- 没有替代命令。
-
脚本名会覆盖内置命令
- 如果
package.json中定义了clean、setup、deploy或rebuild脚本, 那么现在执行pnpm <name>时会优先运行脚本本身,而不是内置命令; - 如需强制执行内置命令,可使用:
pnpm pm <name>。
- 如果
更多内容见 github.com/pnpm/pnpm/b...
四、Demo模拟解决流程
我在本地建了一个配置文件用于模拟当时的情况。此时的package.json中的格式是v10的格式,但pnpm真实的version已经是11.0.8了。
原始文件目录
text
d:\test\
├── package.json
package.json
json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devEngines": {
"packageManager": {
"name": "pnpm",
"version": "^11.0.8",
"onFail": "download"
}
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
},
"type": "module",
"devDependencies": {
"esbuild": "0.25.5",
"vite": "^6.4.2"
}
}
此时在install就会报错

根据官方文档,v11的pnpm不再从package.json的pnpm中读取配置,而是转移到了pnpm-workspace.yaml。这里可以选择手动操作,当然也可以选择官方提供的自动命令。

bash
cd /path/to/your/project
pnpx codemod run pnpm-v10-to-v11
运行命令后会出现一个pnpm-workspace.yaml文件
yaml
allowBuilds:
esbuild: set this to true or false
这个文件表示允许这些以来在安装阶段执行其生命周期脚本,我们可以手动设置为true,或运行指令来设置
bash
pnpm approve-builds esbuild
设置完后就完成升级了。这只是我的项目遇到的问题,官方文档中还讲解了一些必须手动设置的情况,大家根据自己的情况去操作就好。
五、参考链接(官方)
-
Migrating from v10 to v11(简体中文)
pnpm.io/zh/migratio... -
Migrating from v10 to v11(英文)
pnpm.io/11.x/migrat... -
pnpm 11.0 发布说明
pnpm.io/blog/releas... -
pnpm approve-builds 命令
pnpm.io/cli/approve... -
pnpm-workspace.yaml / Workspace 说明
pnpm.io/pnpm-worksp...
pnpm.io/workspaces -
Settings(含各类可在 workspace 中声明的配置索引)
pnpm.io/settings -
GitHub:pnpm v11 变更与讨论 (需要细节时查阅)
github.com/pnpm/pnpm/r...
结语
这类问题的关键词不是「esbuild 坏了」,而是 pnpm 在 major 升级后对「依赖脚本」与「配置位置」做了结构性调整 。把 允许构建的包 写进 pnpm-workspace.yaml 、固定 CI 的 pnpm 版本,能显著减少「合并即发版」路径上的不确定性。
