1011 字
约 3 分钟
0
pnpm 入门:为什么它是下一代包管理器

pnpm 入门:为什么它是下一代包管理器

同样的项目,npm 装要 3 分钟、占 1.2 GB,pnpm 装要 40 秒、占 300 MB。这篇讲它凭什么。

包管理器的痛点演进史

npm 是 Node 自带的包管理器,但它有两个老毛病:

磁盘浪费。你有 10 个项目都依赖 lodash,npm 会在每个项目的 node_modules 里各放一份 lodash——完全相同的代码存了 10 遍。

幽灵依赖。npm 早期把所有依赖拍平塞进顶层 node_modules:你的 package.json 只声明了 A,但 A 依赖的 B 也被提升到了顶层,于是你的代码里 import B 居然能跑——B 根本不是你声明的依赖!这就是幽灵依赖。一旦哪天 A 升级不再依赖 B,你的代码莫名其妙崩了。

yarn 修了安装速度,但磁盘结构和 npm 一样。pnpm(performant npm)对这两个病根同时下了刀。

pnpm 的核心设计:内容寻址存储

pnpm 把所有下载过的包全局只存一份(在 ~/.pnpm-store),以文件内容哈希寻址。项目里的 node_modules 里放的其实是硬链接——不占额外磁盘空间的「另一份引用」。

全局存储(唯一真身)
  ~/.pnpm-store/files/ab/cd1234...(按内容哈希存)
        ↑ 硬链接
项目的 node_modules/lodash/...

10 个项目用 lodash 1.5,磁盘上只有一份。装包也快:哈希命中就直接链接,不重新下载解压。升级版本时,改动的文件才新增存储,没变的文件继续共享。

解决幽灵依赖:非拍平的 node_modules

pnpm 的 node_modules 长这样:

node_modules/
  .pnpm/            ← 所有包的真实位置,按 包名@版本 组织
  express -> .pnpm/express@4.18.2/node_modules/express   ← 只有直接依赖有软链

顶层只放你 package.json 里声明过的依赖的软链接。express 内部依赖的 body-parse?它在 .pnpm/express@4.18.2/node_modules/ 里,只有 express 自己能访问到——Node 的模块解析规则天然保证了这一点。

于是 import bodyParser(你没声明过的包)在 pnpm 项目里直接报错。这不是刁难,是把「依赖关系是否诚实」从君子协定变成了机器强制。

常用命令对照

pnpm install          # 装 package.json 全部依赖(npm install)
pnpm add axios        # 装并写入 dependencies(npm install axios)
pnpm add -D vitest    # 开发依赖(npm install -D)
pnpm remove axios     # 移除
pnpm update           # 更新
pnpm dlx astro ...    # 临时执行包命令(npx astro)
pnpm store prune      # 清理全局存储中未被引用的包

命令几乎是 npm 的同位替换,迁移成本接近零。本站的 package.json 里还有一行:

"preinstall": "npx only-allow pnpm"

这是「防呆锁」:有人用 npm install 时会直接报错退出,强制团队统一包管理器——两种管理器混用会破坏 pnpm 的链接结构。

版本锁定:pnpm-lock.yaml

pnpm-lock.yaml 记录每个包的精确版本、下载地址、完整性哈希。提交到 Git 后,任何人、任何 CI 上 pnpm install --frozen-lockfile 都会装出一模一样的依赖树。本站 CI 就用这个参数,保证本地和流水线环境严格一致。

monorepo 场景 pnpm 还有 workspace 能力(一个仓库管多个包,互相引用零成本),这是它被大项目普遍采用的原因之一。

什么时候选 pnpm

新项目直接用它,没有理由犹豫。存量项目迁移也简单:删掉 node_modules 和 package-lock.json,pnpm import 转换锁文件,pnpm install 完事。唯一要注意的是上面说的幽灵依赖——迁移后你的代码可能会暴露出从未声明过的依赖,补上声明就好,这是修 bug 不是 pnpm 制造 bug。

小结

pnpm 赢在两件事:内容寻址存储让磁盘和安装时间断崖式下降,非拍平的 node_modules 让依赖关系回归诚实。它不是「更快的 npm」,而是把包管理这件事的结构修正了。

pnpm 入门:为什么它是下一代包管理器
http://www.clxhxhhr.top/posts/3711/
作者
clxstart
发布于
2026-09-25
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。