pnpm包管理工具

113 阅读4分钟

npm/yarn存在的问题

幽灵依赖/非法访问

明明我没有手动下载a(package.json中),但是我可以用引用a;

为啥会这样

使用npm/yarn下载包的时候,如果某个依赖包A依赖了a,由于依赖提升,npm/yarn会把A和a放在node_modules同级目录下,而importrquire可以引入node_modules下的包;a就是幽灵依赖,这样就造成了非法访问

存在的问题
  1. 在单项目中 如果我们用了a@1.0版本的某个api,有一天A包升级了,a@1.0也升级到了2.0,并且废弃掉了你用的那个api或者说A包不依赖a包了。这样的话项目就会报错。

  2. monorepo项目中 如果A项目依赖x, B项目依赖x,C项目不依赖x,但是C项目中用到了x.由于依赖提升存在,x会被提升到根目录的node_modules中,那么这样C项目在本地能跑起来,但是C单独发包,用户安装C,那么x就找不到了,会报错.

依赖结构的不确定性

扁平化算法本身的复杂性很高,耗时较长

依赖结构不确定性(lock 文件可以解决 npm5+已经解决)

因为一个包是可能有多个版本的,然后存在不同的包依赖不同版本的情况,包提升只能提升一个,所以后面再遇到相同包的不同版本,就不会提升了,依然还是用嵌套的方式,到底是哪个包被依赖,哪个包被平铺,这是无法确定的(取决于包 在 package.json中的位置)

比如: A依赖c@1.0版本,B依赖c@2.0版本 扁平化以后,始终会有一个版本是嵌套依赖的 A B c\@1.0 B嵌套c\@2.0或者 A B c\@2.0 A嵌套c\@1.0

lock 文件已经解决了依赖结构不确定的问题 yarn.lock和npm5+以上的.lock

嵌套依赖

不同的包依赖不同版本,包提升只能提升一个,所以存在嵌套依赖

存在嵌套依赖所以也会浪费磁盘空间,下载的时候也会多下几个包,所以下载速度也会慢

pnpm

软硬连接

硬连接就是同一个文件有不同引用(多个文件名都表示一个文件),而软链接是新建一个文件,文件内容指向另一个路径。这两种表面上是差不多的. 软硬连接的详细解释

pnpm用了link的方式. 总的来说:包是从全局 store(磁盘) 硬连接到虚拟 store(node_modules/.pnpm)的,而包与包的依赖关系是软连接的;

下面是pnpm官方提供的原理图 一图胜千言 image

因为pnpm是通过link的方式,所以可以跨项目地共享同一版本的依赖! 挖个坑(很利于monorepo项目的形式) pnpm中文文档

pnpm简单工作流程

在项目中执行pnpm install的时候,如果依赖包存在于store中,直接创建依赖包硬链接到store中,如果不存在,则从远程下载后存储在store中,并从项目的node_modules依赖包中创建硬链接到store中。 避免了二次安装带来的时间消耗.

怎么解决问题上述问题的

幽灵依赖/非法访问 得益于与pnpm的这种包管理方式,pnpm不存在这种问题了.

因为node_modules下的包(文件)和package.json的依赖对应起来了,你能import或者require的都是你自己下的包.

依赖的不确定性 依赖的不确定性是因为一个包是可能有多个版本的,然后存在不同的包依赖不同版本的情况,包提升只能提升一个

pnpm的依赖管理方式让node_modules下第一层目录只会存在package.json中的包

参考文档

juejin.cn/post/712138…

juejin.cn/post/711575…

pnpm.io/zh/how-peer…

总结

这也是pnpm团队的初衷

节约磁盘空间并提升安装速度

  1. 相同依赖安装一次,可以跨项目共享同版本依赖
  2. 依赖版本变动只添加有差异的文件

创建非扁平化的 node_modules 文件夹

  1. 避免了非法访问

最后

本文章为笔者学习总结记录贴,后续可能会更新

官网-常用pnpm命令