合并发版时遭遇 ERR_PNPM_IGNORED_BUILDS:从现象到 pnpm v11 迁移

本文记录一次典型的「本地好好的,合并进发版分支后 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.jsonpnpm 字段里的配置,需要迁到仓库根目录的 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 配置"和"其他配置"两部分;
  • onlyBuiltDependenciesneverBuiltDependenciesignoredBuiltDependenciesonlyBuiltDependenciesFile 合并为一个单一的 allowBuilds 映射;
  • managePackageManagerVersionspackageManagerStrictpackageManagerStrictVersion 合并为新的 pmOnFail 配置;
  • 重命名配置项:
    • allowNonAppliedPatchesallowUnusedPatches
    • auditConfig.ignoreCvesauditConfig.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 中定义了 cleansetupdeployrebuild 脚本, 那么现在执行 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

设置完后就完成升级了。这只是我的项目遇到的问题,官方文档中还讲解了一些必须手动设置的情况,大家根据自己的情况去操作就好。

五、参考链接(官方)


结语

这类问题的关键词不是「esbuild 坏了」,而是 pnpm 在 major 升级后对「依赖脚本」与「配置位置」做了结构性调整 。把 允许构建的包 写进 pnpm-workspace.yaml固定 CI 的 pnpm 版本,能显著减少「合并即发版」路径上的不确定性。

相关推荐
invicinble2 小时前
前端框架使用vue-cli( 第三层:插件配置层)
前端·vue.js·前端框架
Hello--_--World3 小时前
React:useState 函数式更新、useContext 全解析、useReducer 深度解析
前端·react.js·前端框架
invicinble3 小时前
前端框架使用vue-cli(总篇章介绍)
前端·vue.js·前端框架
invicinble4 小时前
前端框架使用vue-cli( 第一层:依赖与环境层)
前端·vue.js·前端框架
invicinble4 小时前
前端框架使用vue-cli (第五层:构建打包层--vue.config.js文件介绍以及环境文件)
javascript·vue.js·前端框架
WayneYang1 天前
Nuxt 3 + Vue 3 + TypeScript 全栈开发知识点汇总(2026 最新版)
前端框架·全栈
weixin79893765432...1 天前
React 系统的梳理
react.js·前端框架
QD_ANJING1 天前
建议5月的Web前端开发都去飞书上准备面试...
前端·人工智能·面试·职场和发展·前端框架·状态模式·ai编程
kyriewen112 天前
你等的Babel编译,够喝三杯咖啡了——用Rust重写的SWC,只需眨个眼
开发语言·前端·javascript·后端·性能优化·rust·前端框架