pnpm包管理器详解
前言
pnpm,全称是”performant npm”,意为”高性能的npm”,是一个现代的 JavaScript 包管理工具,类似于 npm 和 Yarn,用来管理项目中的依赖包。
优势
高效的磁盘利用
pnpm 采用了独特的硬链接(hard link)技术,把所有项目共用的依赖包存放在全局的缓存目录里,不同项目之间不会重复安装相同的包,节省磁盘空间。快速安装
因为依赖共享在缓存,安装速度比传统的 npm 和 Yarn 更快,尤其是在多个项目都使用相同依赖时优势明显。严格的依赖隔离
pnpm 默认用的是严格的节点模块结构,避免了”平滑依赖”问题,能帮你发现项目中缺失的依赖,减少”偶然能运行”的情况,提高代码的可维护性。兼容 npm/Yarn
pnpm 能安装 npm registry 上的包,且支持大多数 npm/yarn 的命令和配置,切换成本低。支持工作区(monorepo)
pnpm 原生支持 monorepo 项目结构,方便管理多个包的复杂项目。
为什么使用 pnpm
在使用之前,先了解 npm 和 yarn(特指 yarn v1)存在的问题。
扁平化的 node_modules 解决了”依赖地狱”问题,但出现了以下问题:
1. 幽灵依赖(Phantom Dependencies)
举个例子:你的项目只安装了 A 包(npm install A)。但是 A 包自己依赖了 B 包。因为是扁平化结构,B 包也会被提升到 node_modules 的根目录。
结果就是,你在你的代码里,明明没有在 package.json 里声明过 B,但你却可以 import B from 'B',而且代码还能正常运行!
这就是”幽灵依赖”。它像一个幽灵,让你的项目依赖关系变得混乱不堪。万一有一天,A 包升级了,不再依赖 B 了,你的项目就会在某个意想不到的地方突然崩溃。
2. 磁盘空间的巨大浪费
如果你电脑上有 10 个项目,这 10 个项目都依赖了 lodash,那么在 npm/yarn 的模式下,你的磁盘上就会实实在在地存着 10 份 一模一样的 lodash 代码。
3. 安装速度的瓶颈
虽然 npm 和 yarn 都有缓存机制,但在安装依赖时,它们仍然需要做大量的 I/O 操作,去复制、移动那些文件。当项目越来越大,node_modules 动辄上 G 的时候,安装速度会很慢。
符号链接
1. 彻底告别”幽灵依赖”
在 pnpm 的 node_modules 里,你只会看到你在 package.json 里 明确声明 的那些依赖。
你项目里依赖的 A 包,它自己所依赖的 B 包,会被存放在 node_modules/.pnpm/ 这个特殊的目录里,然后通过 符号链接(Symbolic Link) 的方式,链接到 A 包的 node_modules 里。
这意味着,在你的项目代码里,你根本访问不到 B 包。你想 import B?对不起,直接报错。这就从结构上保证了,你的项目依赖关系是绝对可靠和纯净的。
2. 磁盘空间的”终极节约”
pnpm 会在你的电脑上创建一个”全局内容可寻址存储区”(content-addressable store),通常在用户主目录下的 .pnpm-store 里。
你电脑上所有项目的所有依赖,都只会在这个全局仓库里,实实在在地只存一份。
当你的项目需要 lodash 时,pnpm 不会去复制一份 lodash 到你的 node_modules 里,而是通过 硬链接(Hard Link) 的方式,从全局仓库链接一份过来。硬链接几乎不占用磁盘空间。
这意味着,就算你有 100 个项目都用了 lodash,它在你的硬盘上也只占一份的空间。这个特性,对于磁盘空间紧张的同学来说,简直是福音。
3. 极速的安装体验
因为大部分依赖都是通过”链接”的方式实现的,而不是”复制”,所以 pnpm 在安装依赖时,大大减少了磁盘 I/O 操作。
它的安装速度,尤其是在有缓存的情况下,或者在安装一个已经存在于全局仓库里的包时,几乎是”秒级”的。这种”飞一般”的感觉,一旦体验过,就再也回不去了。

