
最近,我在我们前端团队里推行了一个"强制性"的规定:所有新项目,必须使用pnpm
作为包管理工具;所有老项目,必须在两个月内,逐步迁移到pnpm
。
这个决定,一开始在团队里是有阻力的。
有同事问:"老大,npm用得好好的,为啥非要换啊?我们都习惯了。"
也有同事说:"yarn不也挺快的吗?再换个pnpm,是不是在瞎折腾?"
我理解大家的疑问。但我之所以要用"强制"这个词,是因为在我看来,在2025年的今天,继续使用npm或yarn,就像是明明有高铁可以坐,你却非要坚持坐绿皮火车一样,不是不行,而是没必要。
这篇文章,我就想把我的理由掰开揉碎了,讲给大家听。
npm和yarn的"原罪":那个又大又慢的node_modules
在聊pnpm的好处之前,我们得先搞明白,npm和yarn(特指yarn v1)到底有什么问题。
它们最大的问题,都源于一个东西------扁平化的node_modules
。
你可能觉得奇怪,"扁平化"不是为了解决npm v2时代的"依赖地狱"问题吗?是的,它解决了老问题,但又带来了新问题:
1. "幽灵依赖"(Phantom Dependencies)
这是我最不能忍受的一个问题。
举个例子:你的项目只安装了A
包(npm install A
)。但是A
包自己依赖了B
包。因为是扁平化结构,B
包也会被提升到node_modules
的根目录。
结果就是,你在你的代码里,明明没有在package.json
里声明过B
,但你却可以import B from 'B'
,而且代码还能正常运行!
这就是"幽灵依赖"。它像一个幽灵,让你的项目依赖关系变得混乱不堪。万一有一天,A
包升级了,不再依赖B
了,你的项目就会在某个意想不到的地方突然崩溃,而你甚至都不知道B
是从哪来的。
2. 磁盘空间的巨大浪费
如果你电脑上有10个项目,这10个项目都依赖了lodash
,那么在npm/yarn的模式下,你的磁盘上就会实实在在地存着10份 一模一样的lodash
代码。
对于我们这些天天要开好几个项目的前端来说,电脑的存储空间就这么被日积月累地消耗掉了。
3. 安装速度的瓶颈
虽然npm和yarn都有缓存机制,但在安装依赖时,它们仍然需要做大量的I/O操作,去复制、移动那些文件。当项目越来越大,node_modules
动辄上G的时候,那个安装速度,真的让人等到心焦。
pnpm是怎么解决这些问题的?------"符号链接"
好了,现在主角pnpm登场。pnpm的全称是"performant npm",意为"高性能的npm"。它解决上面所有问题的核心武器,就两个字:链接。
pnpm没有采用扁平化的node_modules
结构,而是创建了一个嵌套的、有严格依赖关系的结构。
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操作。
它的安装速度,尤其是在有缓存的情况下,或者在安装一个已经存在于全局仓库里的包时,几乎是"秒级"的。这种"飞一般"的感觉,一旦体验过,就再也回不去了。
为什么我要"强制"?
聊完了技术优势,再回到最初的问题:我为什么要"强制"推行?
因为包管理工具的统一,是前端工程化规范里最基础、也最重要的一环。
如果一个团队里,有人用npm,有人用yarn,有人用pnpm,那就会出现各种各样的问题:
- 不一致的
lock
文件 :package-lock.json
,yarn.lock
,pnpm-lock.yaml
互相冲突,导致不同成员安装的依赖版本可能不完全一致,引发"在我电脑上是好的"这种经典问题。 - 不一致的依赖结构:用npm的同事,可能会不小心写出依赖"幽灵依赖"的代码,而用pnpm的同事拉下来,代码直接就跑不起来了。
在一个团队里,工具的统一,是为了保证环境的一致性和协作的顺畅。而pnpm,在我看来,就是当前这个时代下,包管理工具的"最优解"。
所以,这个"强制",不是为了搞独裁,而是为了从根本上提升我们整个团队的开发效率和项目的长期稳定性。
最后的经验
从npm到yarn,再到pnpm,前端的包管理工具一直在进化。
pnpm用一种更先进、更合理的机制,解决了过去遗留下的种种问题。它带来的不仅仅是速度的提升,更是一种对"依赖关系纯净性"和"工程化严谨性"的保障。
我知道,改变一个人的习惯很难。但作为团队的负责人,我有责任去选择一条更高效、更正确的路,然后带领大家一起走下去。
如果你还没用过pnpm,我强烈建议你花十分钟,在你的新项目里试一试🙂。