都2022年了,pnpm还不快到碗里来

pnpm是一个新兴的包管理工具,以其快速的安装速度和磁盘空间效率受到关注。文章探讨了npm、yarn存在的问题,如幽灵依赖和NPM分身,并介绍了pnpm的网状+平铺的node_modules结构如何解决这些问题。通过使用hard link和symbolic link,pnpm实现了性能提升,减少了文件下载数量。此外,文章还详细阐述了pnpm的store、links、peerDependencies、workspace等功能,以及与npm、yarn的区别,并提供了常用命令的使用示例。
摘要由CSDN通过智能技术生成

pnpm是一款当代备受关注的 新兴(问题较多) 包管理工具,使用过的同学们都会被它极快的安装速度、极少的磁盘存储空间所吸引!

首先,为什么会出现pnpm?作者一开始对yarn的发布有很高的期待,但是发布后并没有满足作者的一些期待,反而让作者有些失望。

After a few days, I realized that Yarn is just a small improvement over npm. Although it makes installations faster and it has some nice new features, it uses the same flat node_modules structure that npm does (since version 3). And flattened dependency trees come with a bunch of issues
几天后,我意识到 Yarn 只是对 npm 的一个小小的改进。尽管它使安装速度更快,并且具有一些不错的新功能,但它使用与npm相同的平面node_modules结构(自版本 3 起)。扁平化的依赖树带来了一系列问题(具体后面会讲)

至于为什么叫pnpm?是因为pnpm作者对现有的包管理工具,尤其是npmyarn的性能特别失望,所以起名叫做perfomance npm,即pnpm(高性能npm)

如何突显pnpm的性能优势?在pnpm官网上,提供了一个benchmarks图表,它比对了项目在npm、pnpm、yarn(正常版本和PnP版)中,installupdate场景下的耗时:

image.png

下面表格是上图中的具体数据:

action cache lockfile node_modules npm pnpm Yarn Yarn PnP
install 1m 12.2s 15.7s 22.1s 27.5s
install 1.6s 1.3s 2.6s n/a
install 9.5s 4s 8.6s 1.9s
install 14.2s 7.9s 14.2s 7.4s
install 25.4s 13s 15.3s 21.1s
install 2.1s 1.8s 8.3s n/a
install 1.6s 1.4s 9.4s n/a
install 2.1s 5.9s 15s n/a
update n/a n/a n/a 1.6s 12.1s 18.7s 32.4s

可以看到pnpm(橘色)有很明显性能提升,在我们项目实践中(基于gitlib)提升更明显cache-pathsstore dir搭配使用后)

在讨论性能提升原因之前,我们需要先了解下现有包管理工具中node_modules存在的问题

node_modules 安装方式

目前有两种安装方式:`Nested installation`、`Flat installation`

Nested installation 嵌套安装

npm@3 之前,node_modules结构是干净可预测的,因为node_modules 中的每个依赖项都有自己的node_modules文件夹,在package.json中指定了所有依赖项。例如下面所示,项目依赖了foofoo又依赖了bar,依赖关系如下图所示:

node_modules
└─ foo
   ├─ index.js
   ├─ package.json
   └─ node_modules
      └─ bar
         ├─ index.js
         └─ package.json

上面结构有两个严重的问题:

  • package中经常创建太深的依赖树,这会导致 Windows 上的目录路径过长问题

  • 当一个package在不同的依赖项中需要时,它会被多次复制粘贴并生成多份文件

Flat installation 扁平安装

为了解决上述问题,npm 重新考虑了node_modules结构并提出了扁平化结构。在npm@3+yarn中,node_modules 结构变成如下所示:

node_modules
├─ foo
|  ├─ index.js
|  └─ package.json
└─ bar
   ├─ index.js
   └─ package.json

可以看到,hoist机制下,bar被提升到了顶层。如果同一个包的多个版本在项目中被依赖时,node_modules结构又是怎么样的?

例如:一个项目App直接依赖了A(version: 1.0)C(version: 1.0)AC都依赖了不同版本的B,其中A依赖B 1.0C依赖B 2.0,可以通过下图清晰的看到npm2npm3+结构差异:

image.png

B 1.0被提升到了顶层,这里需要注意的是,多个版本的包只能有一个被提升上来,其余版本的包会嵌套安装到各自的依赖当中(类似npm2的结构)。

image.png

至于哪个版本的包被提升,依赖于包的安装顺序!

依赖变更会影响提升的版本号,比如变更后,有可能是B 1.0 ,也有可能是 B 2.0被提升上来(但只能有一个版本提升)

细心的小伙伴可能发现,这其实并没有解决之前的问题,反而又引入了新的问题

image.png

npm3+和yarn存在的问题

Phantom dependencies 幽灵依赖

Phantom dependencies 被称之为幽灵依赖幻影依赖,解释起来很简单,即某个包没有在package.json 被依赖,但是用户却能够引用到这个包。

引发这个现象的原因一般是因为 node_modules 结构所导致的。例如使用 npm或yarn 对项目安装依赖,依赖里面有个依赖叫做 foofoo 这个依赖同时依赖了 bar,yarn 会对安装的 node_modules 做一个扁平化结构的处理,会把依赖在 node_modules 下打平,这样相当于 foobar 出现在同一层级下面。那么根据 nodejs 的寻径原理,用户能 require 到 foo,同样也能 require 到 bar

nodejs的寻址方式:(查看更多)

  1. 对于核心模块(core module) => 绝对路径 寻址

  2. node标准库 => 相对路径寻址

  3. 第三方库(通过npm安装)到node_modules下的库:        3.1.  先在当前路径下,寻找 node_modules/xxx
           3.2  递归从下往上到上级路径,寻找 ../node_modules/xxx
           3.3  循环第二步
           3.4  在全局环境路径下寻找 .node_modules/xxx

NPM doppelgangers NPM分身

这个问题其实也可以说是 hoist 导致的,这个问题可能会导致有大量的依赖的被重复安装.

举个例子:项目中有packageApackageBpackageCpackageD

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值