deadline是第一生产线,在本Q的最后一天,在团队小伙伴们都有或多或少的文章产出的压力之下,终于我也难产出这一篇文章。
要想了解 pnpm 的优势在哪里,知道它解决了什么问题,就要知道 pnpm 的作者在开发 pnpm 的时候,他认为的 npm/yarn 的弱点在哪里。
npm/yarn扁平化的安装机制
以npm@3+的安装机制为例: 图片源自:npm install模块安装机制
npm install安装是在确定了包的版本后,获取包信息,构建依赖树然后进行扁平化处理,将所有依赖包安装在同一层级。
扁平化后的node_modules
目录如下:
node_modules
├─ foo
| ├─ index.js
| └─ package.json
└─ bar
├─ index.js
└─ package.json
在使用依赖包的过程中,所有依赖都在同一层级去找,解决了npm@3
之前的版本以下问题:
- 将所有依赖包安装成树结构之后,大量重复的安装了依赖,造成安装速度非常慢,磁盘空间管理非常差
- 依赖的层级太深导致文件路径过长
但是依赖扁平化后,就会出现下列问题:
- 模块可以访问没有声明依赖的包
- 扁平化一个依赖树的算法非常复杂(耗时)
- 在项目的中有一些包被重复安装
第一个问题在前司遇到过,有时在一个项目中,并没有声明对某个包的依赖,但是却可以使用,而在其他包的依赖中升级了或者移除这个依赖包时,就会出现错误。
问题3我没有理解,在下面这篇文章中找到了答案👇
@作者:神三元 关于现代包管理器的深度思考——为什么现在我更推荐 pnpm 而不是 npm/yarn?
讲解如下:
假如现在项目依赖两个包 foo 和 bar,这两个包的依赖又是这样的:
那么 npm/yarn install 的时候,通过扁平化处理之后,究竟是这样
还是这样?
答案是: 都有可能。取决于 foo 和 bar 在
package.json
中的位置,如果 foo 声明在前面,那么就是前面的结构,否则是后面的结构。这就是为什么会产生依赖结构的
不确定
问题,也是lock 文件
诞生的原因,无论是package-lock.json
(npm 5.x才出现)还是yarn.lock
,都是为了保证 install 之后都产生确定的node_modules
结构。尽管如此,npm/yarn 本身还是存在
扁平化算法复杂
和package 非法访问
的问题,影响性能和安全。
不扁平化,pnpm如何解决问题
树结构会出现问题,扁平化后也会出现问题,那么pnpm是怎么解决的呢?
pnpm在安装时,将每一个包,和它们的依赖放到同一个文件夹中。将依赖提升至和包同一层级。同时,形成与依赖树结构一致的软链接,标注每一个依赖的位置。
以express为例,当包安装完成后,我们可以看到在项目的 node_modules
文件夹下,目录结构是这样的:
.pnpm
.modules.yaml
express
再打开express
▾ node_modules
▸ .pnpm
▾ express
▸ lib
History.md
index.js
LICENSE
package.json
Readme.md
.modules.yaml
这里的express只是一个符号链接
,当 Node.js
解析依赖的时候,它使用这些依赖的真实位置,所以它不保留符号链接。而依赖包的真正位置,在.pnpm
目录下。虽然.pnpm
目录中是扁平化的结构,但是软连接的结构与依赖树完全一致。这样也解决了包的重复安装和对文件的使用权限问题。
这样的机制带来哪些优势
-
npm/yarn在不同项目依赖同一个包的情况下,会将这个包安装多次在每个项目中,而pnpm安装的包会存储在可寻址的磁盘中,在多个项目同时引用时,只需要用一个硬链接指向该地址就可以使用,大大节约了磁盘空间
-
当依赖了同一个包的不同版本时,只对变更的文件进行更新,不需要重复下载没有变更的部分,对于时间和空间
-
算法比 npm/yarn 的扁平化算法简单很多,节省时间
pnpm 使用
安装
直接按照官网方法安装就ok 👉 pnpm.io/zh/installa…
使用
npm 命令 | pnpm 等效 |
---|---|
npm install | pnpm install |
npm i <pkg> | [pnpm add <pkg> ] |
npm run <cmd> | [pnpm <cmd> ] |
基本用法与npm大差不差,但是在配置上, pnpm 比 npm 更严格。
pnpm 支持丰富选择器语法,可以通过名称或关系选择包。
可以通过 --filter
标志指定选择器:
pnpm <command> --filter <package_selector>
详细配置信息可在官方文档查询 👉 pnpm.io/zh/package_…
参考资料:
- pnpm.io/zh/ (官方文档)
- Why should we use pnpm? 以及上文提到的文章