搞懂npm/yarn/pnpm遗留问题和改进历史、对比

137 阅读5分钟

特点

npm@3
  1. npm 是 Node.js 的默认包管理器,拥有庞大的生态系统和广泛的社区支持。
  2. npm 会将包的压缩版本下载并存储在本地缓存中。下次安装相同版本的包时,npm 可以直接从缓存中读取,而不需要重新从远程仓库下载。
  3. 无自动清理。
  4. npm 的缓存则更多是针对单个项目的。
Yarn@1
  1. Yarn 不仅缓存了包的压缩版本,还缓存了包的解压内容,这意味着 Yarn 可以更快地安装包,因为它不需要每次都解压包。
  2. 会自动清理旧缓存内容。
  3. Yarn 的缓存可以被多个项目共享。
pnpm
  1. 和yarn一样,不仅缓存了包的压缩版本,还缓存了包的解压内容。
  2. 节省磁盘空间,因为依赖被存储在一个全局的存储中,并通过硬链接的方式引用。
  3. pnpm 的缓存自动清理机制更先进,因为它会删除不再被任何项目依赖的包,而 Yarn 主要基于时间来清理缓存。
  4. pnpm 的这种缓存机制使得它在处理多个项目时特别高效,使用全局存储和符号链接来跨项目共享相同的包文件。

包管理工具-发展史

开山:npm@3之前的遗留问题

在npm@3之前是嵌套安装,每一个依赖中都有自己的node_modules文件夹,

  1. 如果依赖树过长,那么文件夹路径也会很长。
  2. 当一个依赖包在不同的依赖项中都需要引用时,那么本地磁盘会存储多个相同的包,比如A和B都依赖C时,这时候C会在A和B的node_modules中分别创建。

image.png

改进:npm@3+、yarn@1的出现

为了解决上述问题,npm@3版本和yarn@1采用了扁平化结构,所有包的node_modules都放在同一层级。 需要注意的是多个版本的包只能有一个版本被提升到最上层node_modules,其余版本的包还是会安装到各自依赖当中。

image.png

其中C-1.0和C-2.0谁会提升上去取决于A和B在package.json中的先后位置。

那么这种根据顺序变化所生成都扁平化结构是不确定的,因此需要使用到yarn.lock或者package-lock.json,它们不仅仅是用来锁定下载源,另一个用处也是用于保证不同用户install的扁平化依赖结构相同,虽然有了这重保险,但是依然是没办法避免新增依赖或者更换依赖,当项目庞大了还很不容易找到问题。

npm@3+、yarn的改进带来的幽灵依赖问题

问题表现是某个包在package.json没有被依赖,回到上图npm@3+/yarn图中,A的依赖被提升到最上层node_modules文件夹中,这时候项目中使用C幽灵依赖本质上和引用A和B没区别。

image.png

这种情况下很容易出现包版本问题,

  1. 当package.json插入了新增依赖后或者调整了依赖顺序后,这个C的版本可能就会变更,项目中的使用可能也可能会出现问题。
  2. 当项目不再依赖A和B时,这时候项目install的时候就找不到了,项目中的直接引用C就会出现问题。

npm@3+、yarn@1改进带来的依赖分身问题

依赖提升机制可能会导致大量的依赖被重复安装。

image.png

如图所示,在npm@3+、yarn@1中,Y-2会存在重复安装,会造成一定的性能损失。

pnpm 解决以上问题

image.png

直接依赖A-1安装后,还会创建一个隐藏文件夹.pnpm,里面以平铺方式存储所有的包,通过包名和版本号来实现不同模块和不同版本的隔离,如A-2,B-1。另外如果有重复的包,那将会跨项目进行复用,如D。由于不存在提升,所以不存在幽灵依赖问题。

存储包方式的方式是通过软连接,将链接到.pnpm的node_modules目录中

由于pnpm使用全局文件夹.pnpm-store来存储所有的项目依赖包和硬链接地址,通过访问这些硬链接可以直接访问文件资源如果依赖在.pnpm-store中存在,那么就可以直接从.pnpm-store中去使用硬链接访问,如果不存在才会去下载,避免重复下载和解压。解决了依赖分身的问题。

使用yarn@1或者npm@3时候,需要注意

npm@3+、yarn@1使用都会不可避免遇到上面的问题(幽灵依赖、依赖分身)。

  1. 使用第三方库时,需要确认一下是否在package.json中存在,如果不存在就要手动添加进去(因为是直接依赖是优先使用的,这样就不受制于幽灵依赖导致的版本混乱问题)
  2. 添加依赖时,尽量在package.json后面引入,避免package.json中间插入依赖导致多个幻影依赖冲突,引起项目引用的依赖版本改变
  3. 删除依赖时,需要注意该依赖所导致的幽灵依赖是否有被引用,这种一般编译会报错,比较好察觉

性能对比

2024-11-23 image.png