pnpm的优势
npm2
npm2 的 node_modules 是嵌套的,包自己的依赖就在包自己的 node_modules 中。
两个问题:
1.如果多个包之间有公共依赖,那这个依赖就会复制很多次,多次占用空间。
2.windows 的文件路径最长是 260 多个字符,这样嵌套是会超过 windows 路径的长度限制的。
yarn
所有的依赖不再一层层嵌套了,而是全部在同一层,这样也就没有依赖重复多次的问题了,也就没有路径过长的问题了。
全部铺平在了一层,展开下面的包大部分是没有二层 node_modules 的:
因为一个包是可能有多个版本的,提升只能提升一个,所以后面再遇到相同包的不同版本,依然还是用嵌套的方式。不过,可以通过 yarn.lock 来锁定依赖版本。
npm3+
npm3+ 和 yarn 很类似,也是铺平,也可以通过 package-lock.json 来锁定版本。
问题在于,铺平会产生幽灵依赖的问题。(当然,幽灵依赖问题不是很大,很多 ide 都会提示)
因为所有依赖都铺平在了 node_modules 里,那对一些子依赖,我们虽然没有单独安装,但也可以直接引入。但是一旦父依赖不再依赖子依赖,那代码就跑不了了,因为没有显示依赖,子依赖不会再被安装。(我的理解是 package.json 里没有子依赖,npm i 时不会安装)
pnpm
link,也就是软硬连接,这是操作系统提供的机制,硬连接就是同一个文件的不同引用,而软链接是新建一个文件,文件内容指向另一个路径。当然,这俩链接使用起来是差不多的。
所有的依赖都是从全局 store 硬连接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依赖。
优势
1.只有1份全局包,其余都是链接,依赖不会多余复制,也不会有长度限制。
2.没有幽灵依赖,因为没有铺平
3.速度快,链接的方式而不是复制
缺陷
装一个包,所有依赖都会装到全局,如果项目删除,依赖仍在全局目录中
可以通过执行 pnpm store prune 删除不再被引用的包
原理在于 硬链接会记录被引用了几次。当没有被的引用的时候就可以删除。(有点像垃圾回收的引用计数吧)