pnpm 是如何解决这两个难题的?

lxf2023-03-18 10:03:01

各位近期是否经常会听到 pnpm,我也一样。今日探讨了一下它体制,的确强大,对 yarn 和 npm 算得上是降维攻击。

那实际好在哪里呢? 我们一起来看一下。

我们按照包管理工具的发展历史,从 npm2 逐渐说起:

npm2

用 node 版本管理工具把 node 版本号降至 4,那 npm 版本号便是 2.x 了。

pnpm 是如何解决这两个难题的?

随后找一个文件目录,实行下 npm init -y,迅速建立个 package.json。

随后实行 npm install express,那样 express 包和它依靠都能被直接下载:

pnpm 是如何解决这两个难题的?

进行 express,它也有 node_modules:

pnpm 是如何解决这两个难题的?

再进行多层,每一个依靠都有各自的 node_modules:

pnpm 是如何解决这两个难题的?

换句话说 npm2 的 node_modules 是内嵌的。

这是正常的呀?有什么不对么?

那样实际上是有问题的,好几个包中间难免有公共性的依赖性,那样嵌入得话,一样的依赖性会拷贝好多次,会占有较大的储存空间。

这一不是问题的核心,致命弱点是 windows 的目标文件夹最多是 260 好几个标识符,那样嵌入会超出 windows 途径长度限制。

那时候 npm 还没有处理,小区就出来新解决方案了,便是 yarn:

yarn

yarn 是如何解决依靠反复好多次,嵌入途径较长的难题的?

刮平。每一个依靠不会再一层层嵌入了,反而是所有在同一个一层,那样就没有依靠反复数次问题了,就没有途径较长的问题。

我们可以把 node_modules 删掉,用 yarn 再重装下,实行 yarn add express:

此刻 node_modules 就是这样了:

pnpm 是如何解决这两个难题的?

所有刮平到了一层,进行下边的包绝大多数都是没有二层 node_modules 的:

pnpm 是如何解决这两个难题的?

不过也有单肩包确实是有 node_modules 的,例如那样:

pnpm 是如何解决这两个难题的?

为何也有嵌入呢?

由于一个包是可能会有好几个版本,提高只有提高一个,但后面再遇见同样包的不一样版本号,依旧还是用嵌入的形式。

npm 之后升级成 3 以后,都是使用这种刮平的解决方案了,和 yarn 十分相似:

pnpm 是如何解决这两个难题的?

自然,yarn 还完成了 yarn.lock 来锁住依靠版本作用,但是这个 npm 也实现了。

yarn 和 npm 都采用了刮平的解决方案,这类计划方案也就没有问题么?

并非,扁平化的计划方案也有明确的难题。

最重要的一个关键是鬼魂依靠,也就是说你压根没有申明在 dependencies 里的依赖性,但编码里却能够 require 进去。

这个其实很好理解,由于都刮平了吗,那依靠的依靠都是都可以找到的。

但这样也是有隐患的,如果没有显式依靠,万一有一天其他包不依附这个包了,那么你的编码可能就不可以溜了,由于你依靠这个包,但现在不被装上。

这便是鬼魂依靠的难题。

并且还有一个问题,便是前面提到的架包有好几个版本情况下,只会提高一个,那其他版本包不或是拷贝了好多次么,仍然有消耗储存空间问题。

那小区是否有处理这两个难题思路呢?

其实有,这个不是 pnpm 就来了嘛。

那 pnpm 是如何解决这两个难题的?

pnpm

回忆下 npm3 和 yarn 为什么做 node_modules 扁平化设计?还不是因为一样的依赖性会拷贝数次,而且途径太长在 windows 底下难题么?

那假如不拷贝呢,比如通过 link。

最先推荐下 link,其实就是薄厚联接,这也是电脑操作系统给予的制度,硬连接便是同一个文件的差异引入,而软链接是创建一个文档,文件信息偏向另一个途径。自然,这两个连接用起来差不太多。

假如不复制文件,只能在全局性库房储存一份 npm 包的具体内容,其他的地方就 link 以往呢?

这样就不会有拷贝多次储存空间消耗,并且也不会有什么途径较长的难题。由于途径较长的限定本质上是不可以什么太深目录层级,现在是每个区域的文件目录的 link,并非同一个文件目录,因此也不会有什么长短限定。

没有错,pnpm 就是利用这类构思来完成的。

然后把 node_modules 删除,随后用 pnpm 再次装一遍,实行 pnpm install。

你就会发现它打印出了这样一句话:

pnpm 是如何解决这两个难题的?

包是以全局性 store 硬连接到虚似 store 的,这儿的虚似 store 便是 node_modules/.pnpm。

大家开启 node_modules 看一下:

pnpm 是如何解决这两个难题的?

确实不是扁平化的了,依靠了 express,那 node_modules 会就仅有 express,并没有鬼魂依靠。

进行 .pnpm 看一下:

pnpm 是如何解决这两个难题的?

每一个依靠就在这里刮平了,也是从全局性 store 硬连接来的,随后包移动和包间的依存关系是由软链接组织。

例如 .pnpm 中的 expresss,这都是软链接,

pnpm 是如何解决这两个难题的?

换句话说,每一个依靠也是从全局性 store 硬连接到 node_modules/.pnpm 下,随后之间通过软链接来相互依存。

官方网给一张电路原理图,配合着看一下就懂了:

pnpm 是如何解决这两个难题的?

这便是 pnpm 的实现基本原理。

那样回过头看一下,pnpm 为何出色呢?

最先,最大的优势是节约储存空间呀,一个包全局性只储存一份,剩下的都是薄厚联接,这个要节约是多少储存空间呀。

再者就是快,因为通过连接的方法而非拷贝,当然会快。

那也是其所树立的优势:

pnpm 是如何解决这两个难题的?

对比 npm2 的优势就是不容易开展一样依靠的数次拷贝。

对比 yarn 和 npm3 呢,那便是并没有鬼魂依靠,都不会是不是被提高的依赖性仍然拷贝好几份问题。

这就已经足够足够优秀,对 yarn 和 npm 算得上是降维攻击。

汇总

pnpm 近期经常听到,算得上是爆红。文中大家汇总了下它爆红的缘故:

npm2 是由嵌入的形式管理方法 node_modules 的,会有一样的依靠拷贝多次难题。

npm3 和 yarn 是由刮平的扁平化的方法来管理方法 node_modules,克服了嵌入方法的那一部分难题,可是引进了鬼魂依靠的难题,而且同名的单肩包只会提高一个版本,其余版本号仍旧会拷贝数次。

pnpm 则是用了另一种方式,再也不是复制出,反而是都要从全局性 store 硬连接到 node_modules/.pnpm,随后之间通过软链接来机构依存关系。

这样不仅节约储存空间,都没有鬼魂依靠难题,组装速率更快,从体制上来讲完爆 npm 和 yarn。

pnpm 便是凭着这个对 npm 和 yarn 降维攻击的。