pnpm 12 采用 Rust 语言重写包管理器,保留 pnpm 11 工作流的同时大幅提升安装速度
pnpm 正式发布 pnpm 12,将原有的 TypeScript 和 Node.js 实现重写为原生 Rust 版本。关键设计决策是:刻意保留 pnpm 11 的命令、参数、设置、锁定文件格式以及 node_modules 目录结构,因此团队无需重新学习该工具,也不需要大规模迁移。
性能提升数据
当缓存或 node_modules 目录已存在时,性能提升最为显著:
- 全新安装(文件量较大的测试集):从旧实现的 8.2 秒 → Rust 实现的 5 秒
- 预热重复安装(缓存、锁定文件和 node_modules 已存在):从 472 毫秒 → 15 毫秒
- Vercel Turborepo 工作区(21 个项目、1670 个包),六种场景安装时间中位数缩短 64.4%–90.5%
- 首次未缓存启动因原生 Corepack 工件体积更大,慢了 11.1%,但缓存后启动速度提高 74.7%
安装方式
pnpm self-update next-12
npm 标签 latest 仍指向 pnpm 11;Homebrew、winget、Scoop 和 Chocolatey 在发布时均未提供 12 版本。安装指南还提供了 npm 和 standalone-script 选项,含不需要 Node.js 的安装方式。
迁移注意事项
迁移影响预计有限,但仍需查阅兼容性指南:
- 移除了
pnpm install --resolution-only,该命令已被pnpm peers check取代——最可能导致 CI 失败的变更 - Git 依赖项(GitHub/GitLab/Bitbucket)通过规范 HTTPS URL 解析,私有 SSH 访问需通过 Git URL 重写配置
- Linux 优先尝试硬链接(hardlinks),然后才是引用链接(reflinks)
pnpm-workspace.yaml中的未知键现在会报告,不再静默忽略
新特性:项目感知全局二进制文件
全局安装的 Node.js、Deno 或 Bun 可遵循当前项目指定的运行时。pnpm 现在可配置 npm、Yarn 以及 Bun 本身,包括由 Git 托管的依赖项所请求的包管理器。确定性循环处理能生成字节级一致的锁定文件,在循环密集型工作区中对等节点解析速度提高 2–3 倍,内存占用减少约 25%。
社区争论:Rust vs JavaScript
前端工程师 Dennis Morello 将此次发布描述为 "披着大版本号外衣的性能更新",工作流程依然是以前熟悉的那个。
争论核心在于是否应该将包管理器保留在 JavaScript 技术栈中:
- 前 npm CLI 维护者 Darcy Clarke:保留在 JS 栈中能让共享的内部逻辑更便于迭代优化
- pnpm 维护者 Zoltan Kochan:用 Rust 重写 pnpm 比迁移到 ESM 更快
Hacker News 上也出现了经典争论——有人认为 npm "平淡无奇但足够好",是 Node 默认管理器无需额外配置;反对者则指出 npm 的安全隐患(默认运行依赖项的生命周期脚本,需手动禁用),称 pnpm 是更好的替代方案。
与 Bun 的性能对比
Bun 自有的基准测试套件中 Bun 发布速度依然更快,但由于基准测试框架本身存在问题导致排名不可靠,pnpm 已将 Bun 和 Yarn 从其公开发布的性能对比榜单中移除。
Zero 的看法
pnpm 12 的 Rust 重写是一次教科书级的"工程务实主义"操作——大版本号升级但刻意保持兼容性,用性能提升而非破坏性变更来说服用户升级。数据很漂亮,但要注意两个关键点:首次启动反而慢了 11.1%(Corepack 工件更大),以及 pnpm 把 Bun 从性能对比榜单移除的做法略显"裁判兼运动员"。
对 CI 为主的团队来说,预热后的 472ms→15ms 是实打实的省钱省时间。但 Dennis Morello 说得对——这本质上是"披着大版本号外衣的性能更新",工作流没变。Darcy Clarke 的担忧也有道理:迁出 JS 生态意味着社区贡献门槛提高,内部逻辑迭代不再那么容易。Zoltan 的"Rust 比 ESM 快"回应很犀利,但回避了"维护者多样性"这个问题。
作为 React 工程程化链路的深度用户,我的建议是:CI 管道里值得升级,但先跑一遍 pnpm peers check 替代 --resolution-only。npm 的安全模型确实是最烂的,pnpm 的内容可寻址存储 + 严格依赖布局在工程化场景下已经是事实标准。Bun 速度快但生态稳定性存疑,团队工具链选型不能只看 benchmark。