npm2
首先来讲讲最早的npm2,最早的npm2安装依赖后,如果a依赖依赖了其它依赖,那么安装后是嵌套关系,例如我安装了express,express下面还有node_modules,打开node_modules发现里面的包还有node_modules.
这样做会造成两个问题:
- 多个包之间难免会有公共的依赖,这样嵌套的话,同样的依赖会复制很多次,浪费磁盘空间。
- windows 的文件路径最长是 260 多个字符,这样嵌套是会超过 windows 路径的长度限制的。
于是就有了npm3
npm3是采用了铺平的方式解决了重复依赖问题,展开包,也没有node_modules了
但是还是可能会有嵌套,就是一个包有多个版本的时候,平铺只能平铺一个版本的。不过npm和yarn都有lock.json文件来锁定版本,yarn和npm3同理。
但是npm和yarn就会造成两个问题:
-
幽灵依赖
明明没有声明在 dependencies 里的依赖,但在代码里却可以 require 进来。因为依赖都铺平了,例如我的a依赖 依赖了 b,我下载a依赖的时候,node_modules就会出现a和b两个包,此时我的代码中也可以引入b,但是我哪天如果不用a这个包,将他删除,那么代码就会崩掉。
上面说的还是可能会有特殊情况造成有重复依赖的,浪费磁盘空间。
pnpm
这里首先要介绍软链接和硬链接的概念,我就用通俗易懂的方式来介绍:
- 软链接
就类似于我们创建了一个应用的快捷方式,你想卸载应用时,必须删除源文件。 - 硬链接
新建的文件是已经存在的文件的一个别名,当原文件删除时,新建的文件仍然可以使用。类似于深拷贝。
当我们使用pnpm时,发现node_modules没有那么多东西了,只有个.pnpm和express,首先确保了没有幽灵依赖。
所有的依赖都在.pnpm文件中,在这里铺平了,都是从全局 store 硬连接过来。
所有的依赖都是从全局 store 硬连接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依赖。
最大的优点是节省磁盘空间呀,一个包全局只保存一份,剩下的都是软硬连接,这得节省多少磁盘空间呀。
相信大家此刻跟我有一个疑问,那一直往store里存储依赖包,store会不会越来越大?
官方提供了一个命令:
pnpm store prune
,从存储中删除未引用的包。