我们最近是不是常常听到 pnpm,我也相同。今天研讨了一下它的机制,确实凶猛,对 yarn 和 npm 能够说是降维冲击。

那具体好在哪里呢? 我们一同来看一下。

我们依照包揽理工具的发展前史,从 npm2 初步讲起:

npm2

用 node 版别处理工具把 node 版别降到 4,那 npm 版别就是 2.x 了。

pnpm 是凭什么对 npm 和 yarn 降维冲击的

然后找个目录,实行下 npm init -y,快速创建个 package.json。

然后实行 npm install express,那么 express 包和它的依托都会被下载下来:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

翻开 express,它也有 node_modules:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

再翻开几层,每个依托都有自己的 node_modules:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

也就是说 npm2 的 node_modules 是嵌套的。

这很正常呀?有什么不对么?

这样其实是有问题的,多个包之间难免会有公共的依托,这样嵌套的话,相同的依托会拷贝很多次,会占据比较大的磁盘空间。

这个还不是最大的问题,丧身问题是 windows 的文件途径最长是 260 多个字符,这样嵌套是会超过 windows 途径的长度束缚的。

当时 npm 还没处理,社区就出来新的处理方案了,就是 yarn:

yarn

yarn 是怎样处理依托重复很多次,嵌套途径过长的问题的呢?

铺平。一切的依托不再一层层嵌套了,而是悉数在同一层,这样也就没有依托重复多次的问题了,也就没有途径过长的问题了。

我们把 node_modules 删了,用 yarn 再从头设备下,实行 yarn add express:

这时候 node_modules 就是这样了:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

悉数铺平在了一层,翻开下面的包大部分是没有二层 node_modules 的:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

当然也有的包仍是有 node_modules 的,比如这样:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

为什么还有嵌套呢?

因为一个包是可能有多个版其他,进步只能进步一个,所以后边再遇到相同包的不同版别,依然仍是用嵌套的方法。

npm 后来升级到 3 之后,也是采用这种铺平的方案了,和 yarn 很类似:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

当然,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 是凭什么对 npm 和 yarn 降维冲击的

包是从全局 store 硬联接到虚拟 store 的,这儿的虚拟 store 就是 node_modules/.pnpm。

我们翻开 node_modules 看一下:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

确实不是扁平化的了,依托了 express,那 node_modules 下就只有 express,没有鬼魂依托。

翻开 .pnpm 看一下:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

一切的依托都在这儿铺平了,都是从全局 store 硬联接过来的,然后包和包之间的依托联络是通过软链接安排的。

比如 .pnpm 下的 expresss,这些都是软链接,

pnpm 是凭什么对 npm 和 yarn 降维冲击的

也就是说,一切的依托都是从全局 store 硬联接到了 node_modules/.pnpm 下,然后之间通过软链接来相互依托。

官方给了一张原理图,配合着看一下就理解了:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

这就是 pnpm 的完结原理。

那么回过头来看一下,pnpm 为什么优异呢?

首要,最大的利益是节省磁盘空间呀,一个包全局只保存一份,剩余的都是软硬联接,这得节省多少磁盘空间呀。

其次就是快,因为通过链接的方法而不是拷贝,自然会快。

这也是它所标榜的利益:

pnpm 是凭什么对 npm 和 yarn 降维冲击的

比较 npm2 的利益就是不会进行相同依托的多次拷贝。

比较 yarn 和 npm3+ 呢,那就是没有鬼魂依托,也不会有没有被进步的依托依然拷贝多份的问题。

这就现已满足优异了,对 yarn 和 npm 能够说是降维冲击。

总结

pnpm 最近常常会听到,能够说是爆火。本文我们梳理了下它爆火的原因:

npm2 是通过嵌套的方法处理 node_modules 的,会有相同的依托拷贝多次的问题。

npm3+ 和 yarn 是通过铺平的扁平化的方法来处理 node_modules,处理了嵌套方法的部分问题,可是引入了鬼魂依托的问题,并且同名的包只会进步一个版其他,其他的版别依然会拷贝多次。

pnpm 则是用了另一种方法,不再是拷贝了,而是都从全局 store 硬联接到 node_modules/.pnpm,然后之间通过软链接来安排依托联络。

这样不但节省磁盘空间,也没有鬼魂依托问题,设备速度还快,从机制上来说完胜 npm 和 yarn。

pnpm 就是凭借这个对 npm 和 yarn 降维冲击的。