pnpm 是什么
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
pnpm - 速度快、节省磁盘空间的软件包管理器。
同类工具有我们熟悉的npm、yarn。新工具的出现并流行,一定是解决了旧工具的痛点。我们先简单回顾一下npm和yarn的发展以及存在的问题。
npm 和 yarn
npm
在 npm1 和 npm2 中依赖管理是嵌套结构的,如图:
在项目 node_medules 下安装了 express 包,express 又有自己的 node_modules,同样在 express 的 node_modules 中的依赖也会有自己的 node_modules。
存在的问题:
-
依赖层级深,会导致文件路径过长。windows 的文件路径最长是 260 多个字符,这样嵌套是会超过 windows 路径的长度限制的。
-
公共的依赖不能复用,会重复安装很多次,导致文件体积过大,占用大量磁盘空间。
针对这些问题社区有了新的解决方案:yarn。
yarn
通过将依赖铺平,用扁平化依赖管理的方式解决这个问题。
我们用 yarn 重新安装 express 包,项目的 node_modules 如图:
可以看到所有的依赖都安装到项目的 node_modules 下,express 下没有自己的 node_modules 了,没有了很深的依赖嵌套,相同版本的包也不会重复安装。这样解决了公共依赖重复安装的问题,也不会因为很深的依赖层级导致文件路径过长。
npm3 也采用了这种铺平的方案,扁平化依赖管理的方式存在的问题:
-
扁平化算法耗时较长;
-
多个版本的依赖包,只会提升一个,其他版本的依赖包还会重复安装并嵌套使用;
-
项目中可以非法访问未声明的依赖包,也就是幽灵依赖问题。
幽灵依赖问题,就是说在 package.json 中未声明的依赖,可以在代码中引入并使用。原因是依赖都铺平在项目的 node_modules 下,依赖的依赖也可以在 node_modules 下找到。存在的隐患:我们未声明的情况下使用一个依赖包,等哪天这个依赖包不再被其他声明的包依赖,我们的代码就跑不通了,因为这个依赖包没有安装。
针对这些问题,pnpm 出现了。
pnpm的实现方式
同样,我们再用 pnpm 安装 express 包,可以看到有如下提示:
安装包是从内容可寻址存储到虚拟存储的硬链接,内容可寻地址是计算机的文件路径,虚拟存储就是项目 node_modules 下的 .pnpm,是通过硬链接(硬链接指同一个文件的不同引用)。内容可寻地址相当于全局的 store,虚拟存储相当于本地的 store。
项目的 node_modules 如图:
可以看到不再是扁平化结构,只有我们声明的 express。
.pnpm 展开如图:
所有的依赖都在 .pnpm 下铺平了,并且这些依赖全都是从全局 store 硬连接过来的,然后包和包之间的依赖关系是通过软链接(软链接指新建一个文件,文件内容指向另一个路径)组织的。比如 express@4.18.1 的 node_modules 虽然是嵌套结构,但是依赖都是软链接;项目 node_modules 下的 express 也是软链接的方式组织的。
pnpm 就是使用软硬链接的方式解决 npm/yarn 的问题,项目所有的依赖都是从全局 store 硬链接到 node_modules/.pnpm 本地 store 下,然后通过软链接来组织依赖关系。
项目的 node_modules 下不再是各种被铺平的依赖,而是与 package.json 中声明的依赖基本保持一致,结构清晰了也解决了幽灵依赖的问题。
一个依赖包只在全局 store 中保存一份,剩下的都是软硬链接,大大节省了磁盘空间,使用软硬链接方式组织依赖也比复制依赖的速度快了很多。