pnpm 12 升级 CI 避坑:官方说无缝升级,但这七件事不检查会崩

pnpm 12 发布了,官方说”升级不应该感觉像一次迁移”——命令不变、配置不变、lockfile 不变。理论上,你跑一行 pnpm self-update next-12 就完事了。

但如果你管着公司的 CI 流水线,这个”理论上”可能会让你付出一个下午的排查时间。

pnpm 12 做了七项行为变更,其中多数不会在本地复现,只在 CI 环境里炸。以下是每个坑的具体表现和应对方案。

坑一:pnpm install --resolution-only 删了

这是最可能炸 CI 的变更。

pnpm 12 把 pnpm install --resolution-only 这个 flag 直接删了。它的作用是在不真正安装依赖的情况下,解析并校验 lockfile 里所有依赖的版本和 peer 关系。很多 CI 脚本会用这个命令做”依赖预检”。

现在这个命令跑不动了,取而代之的是 pnpm peers check,但后者做的事情不完全一样——peers check 只检查 peer 依赖冲突,不会输出完整的解析结果。

落地:搜一下你们的 CI 脚本和 Dockerfile 里有没有 --resolution-only,有的话改掉:

# 旧
pnpm install --resolution-only

# 新(只做 peer 检查,不做全量解析)
pnpm peers check

如果你的 CI 真的需要”只解析不安装”这个能力,现在只能靠 pnpm install --dry-run 自己解析输出,或者直接装完不管。


坑二:Git 依赖改走 HTTPS,不走 SSH 了

这是另一个在本地几乎感觉不到、但在 CI 里会直接挂的变更。

pnpm 12 把托管在 GitHub、GitLab、Bitbucket 上的 Git 依赖的解析方式,从 SSH URL 改成了规范的 HTTPS URL。这意味着:

  • 原来能用的 git@github.com:org/repo.git 写法,现在会被翻译成 https://github.com/org/repo.git
  • 如果你的 CI 机器没有配置 GitHub HTTPS credentials(只有 SSH key),git clone 会直接失败

落地:在项目根目录加一个 Git URL 重写规则,或者确保 CI 环境有 HTTPS 认证:

# ~/.gitconfig 里加
[url "https://github.com/"]
    insteadOf = git@github.com:

或者在 pnpm-workspace.yaml 里用 pnpm.config.publicUrl 显式指定。


坑三:pnpm-workspace.yaml 里未知的 key 现在会报错

pnpm 12 之前,如果你 workspace 配置文件里写了 pnpm 不认识的 key,它会静默忽略。现在会直接报错。

这在本地一般没事——但如果你的 workspace 配置是从模板或者旧项目里复制过来的,里面有 pnpm install 的旧参数、或者某些 CI 工具写入的元数据字段,现在会直接 panic。

落地

# 先跑一下看有没有问题
pnpm install 2>&1 | grep "Unknown setting"

坑四:Linux 优先硬链接,再试引用链接

pnpm 12 改变了 Linux 上文件链接策略的优先顺序:原来优先引用链接(reflinks,CoW),现在优先硬链接(hardlinks)。

在大多数场景下这不会有问题,但如果你的项目跑在 NFS 或者某些共享文件系统上,硬链接的表现和 reflinks 不一样——硬链接要求源文件和目标在同一文件系统,而 reflinks 更宽松。

落地:如果你用 NFS 或者网络存储,升级后跑一次完整的 pnpm install,确认 node_modules 里文件都正确 link 上了。


坑五:Corepack 首次启动变慢 11%

pnpm 12 的原生二进制比之前大了约 11.1%,这导致通过 Corepack 首次安装 pnpm 时会比之前慢一点(只有首次,后面的缓存安装反而更快了)。

这不是 breaking change,但在 CI 里第一次跑 corepack prepare pnpm@12 时会多等几秒。如果你的 CI 有超时限制,要确认这个超时够用。


坑六:新功能:确定性循环 lockfile

这是新功能,不是 breaking change,但如果你有复杂的 peer 依赖循环(A → B → C → A),pnpm 12 现在能生成字节级确定的 lockfile。这意味着不同机器上跑出来的 lockfile 内容完全一致,可以减少因 lockfile diff 导致的无效 commit。


坑七:pnpm install 之后 store 和 node_modules 占用减少 52.5%

同样是新特性。pnpm 12 在安装后对 store 和 node_modules 做了更彻底的裁剪,磁盘占用平均下降 52.5%。对于大 monorepo 的 CI 缓存来说,这是好消息——每次 install 后占用的空间更少,CI cache 上传下载更快。


升级清单:升级前跑这一遍

# 1. 检查 CI 脚本里有没有 --resolution-only
grep -r "resolution-only" .github/ docker-compose* Makefile .gitlab-ci.yml

# 2. 检查 Git 依赖配置(如果有 private repo)
cat .gitconfig
git config --get-urlmatch url https://github.com/.insteadOf

# 3. 检查 workspace 配置有没有未知 key
pnpm install 2>&1 | grep -i "unknown"

# 4. 升级
pnpm self-update next-12

# 5. 确认版本
pnpm --version  # 应该是 12.x

# 6. 本地跑一遍完整 install + build
pnpm install && pnpm build

速度提升是真实的

说完坑,也要说数字。pnpm 12 的速度提升是实打实的:

  • 清洁安装:8.2 秒 → 5 秒(pnpm 11 → 12)
  • 热缓存安装:472ms → 15ms(提升 96.8%)
  • Vercel Turborepo(1670 个包)全场景提速 64.4% ~ 90.5%

配合新出的 pnpr(Rust 写的 registry server),同一测试可以压到 3.37 秒。

升级的收益远大于代价——只要你在升级前把上面的坑跑一遍。


总结:pnpm 12 本身是推荐升级的。七项变更里真正会影响大多数团队的是前两项(--resolution-only 删除 + Git 依赖 HTTPS),后面几项基本是边缘场景。升级前花十分钟过一遍 CI 脚本,比升级后花两个小时排查要划算得多。

评论区

0 条评论

登录后可评论。