为什么项目应该只用 pnpm
一个项目到底用 npm、yarn 还是 pnpm,看起来只是命令不同。真正做过几次依赖升级、多人协作和持续集成之后,会发现这其实是一个工程约束问题。
我的判断是:项目既然选择了 pnpm,就不应该继续允许 npm 被使用。
混用包管理器,问题不只是一份锁文件
很多项目会出现这样的情况:有人执行 npm install,有人执行 pnpm install,CI 又使用另一套命令。只要项目暂时还能启动,大家就觉得问题不大。
但依赖安装并不是一个完全没有副作用的过程。不同包管理器对依赖树、peer dependency、lockfile 和 node_modules 的处理方式并不完全一样。一次看似普通的安装,可能让锁文件发生变化,也可能让本地能运行的结果和 CI 不一样。
这类问题通常不会立刻暴露。它们更像是被埋在项目里的不确定性:今天没有报错,不代表下次升级依赖时还会一样。
所以,项目真正需要的不是“大家都知道几种包管理器”,而是同一个项目只有一条确定的依赖安装路径。
为什么选择 pnpm
选择 pnpm,最直接的原因是它更适合长期维护的项目。
首先,pnpm 使用内容寻址存储,同一台机器上的多个项目可以复用相同的依赖文件。相比每个项目都完整复制一份依赖,它通常能减少磁盘占用,也能让重复安装更快。
其次,pnpm 的依赖目录结构更严格。项目只能访问自己声明的依赖,不能因为某个间接依赖碰巧出现在扁平化目录里,就直接在代码中使用它。这个限制会让一些隐藏依赖更早暴露出来,反而有利于维护。
当然,pnpm 不是所有场景下的唯一答案。一个老项目如果已经稳定使用 npm,没有必要为了追求工具统一而强行迁移。真正重要的是选定之后持续使用,而不是在工具之间来回切换。
为什么要禁止 npm
如果只在文档里写一句“推荐使用 pnpm”,实际效果通常不够。
“推荐”意味着还有另一条路。新成员可能照着旧文章执行 npm install,自动化脚本可能继续运行 npm ci,某个临时排查问题的人也可能顺手执行 npm run build。这些操作单独看都很合理,但最后会让项目失去唯一的标准。
禁止 npm 的重点,不是认为 npm 这个工具不好,而是不要让同一个项目同时维护两套工作方式。
当项目明确只使用 pnpm 时,安装依赖、执行脚本、更新锁文件和 CI 构建,都应该使用同一套命令。这样出了问题,排查范围会更小,团队也不会争论“到底应该用哪条命令”。
禁止的是 npm 命令,不是 npm registry
这里还需要区分一个容易混淆的地方。
npm 既可以指 npm 包管理器,也常被用来指 npm registry。项目禁止使用 npm install,不等于必须禁止从 npm registry 下载依赖。pnpm 默认仍然可以从 npm registry 获取公开包,这两件事并不矛盾。
真正要禁止的是这些项目操作:
- 用
npm install安装或更新依赖; - 用
npm ci作为 CI 的安装方式; - 用
npm run执行项目脚本; - 提交或继续维护与项目包管理器不一致的 lockfile。
项目可以使用 pnpm install、pnpm add、pnpm run build,并让 CI 使用完全相同的安装和构建方式。
统一工具,减少无意义的选择
开发工具的选择本身不是目的。真正有价值的是把不需要讨论的事情固定下来。
依赖应该怎么装、锁文件由谁生成、CI 用什么安装、脚本用什么执行,这些如果每个人都可以自由选择,项目就会把时间花在工具差异上。统一使用 pnpm,并明确禁止 npm,本质上是在减少一类没有收益的自由度。
对一个需要长期维护的项目来说,少一条隐含路径,就少一种环境差异。不是因为 pnpm 永远正确,而是因为同一个项目不应该同时拥有两套标准。
