现代包管理工具:pnpm

1,477 阅读2分钟

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

pnpm 是一个包管理工具。

pnpm 非常适合**「单仓多包」**的项目,即 monorepo

pnpm 非常快,官网上有个速度PK结果:

pnpm几乎是其他包管理器的2倍多 pnpm几乎是其他包管理器的2倍多

Vue3.0 里就用到了 pnpm

Vue3.0:move to pnpm

Vue3.0:move to pnpm

除了 Vue3.0,还有很多公司和组织也在用 pnpm

https://pnpm.io/users

pnpm.io/users

pnpm不仅速度够快,占用的空间更小,尤其是monorepo项目,一个仓库下的多个项目可共用依赖包,各个项目可通过软链索引到依赖包的实际位置(类似文件夹快捷方式),而不需要每个项目都安装一份,大大节省了存储空间。

依赖包的实际安装位置默认是在 .pnpm 里,在windows下我们可以用 dir 命令看到符号链接实际指向的位置:

pnpm 提供了非常多的配置选项,感兴趣的童鞋可以去官网上自行探索:pnpm.io/zh

在npm3和yarn中,为了解决树型依赖层级太深的问题,采用了一种叫“flat node_modules”的扁平结构,简单理解就是把所有依赖包都提升到 node_modules 根目录下,然后各个包再通过软链索引到实际位置。

但是这种做法不仅算法复杂,还会引起新的问题,即 node_modules 里会有很多**「幽灵依赖包」**(Phantom dependency),可以理解为依赖的依赖(比如我们项目需要依赖 vuevue 又依赖了很多其他包,但是这些包并没有在我们自己的 package.json 里声明)。

pnpm 则不会有这个问题。

pnpm的根目录下的 node_modules 是纯净的,只包含我们在 pakcage.json 中显式声明的依赖包,并且这里实际上保存的是依赖包的软链。

这里以 express 为例,依赖包express 通过软链实际指向了.pnpm\express@4.17.1\node_modules\express

至于依赖的依赖,我们去express依赖包实际所在目录看看:

.pnpm\express@4.17.1\node_modules下不仅保存了 实际的 express 包,还保存了 express 所依赖的包的软链。这些软链同样指向了根目录下node_modules.pnpm中文件夹。

依赖的依赖也是通过软链指向根路径下的包

依赖的依赖也是通过软链指向根路径下的包。

实际位置

这种做法不仅避免了“幽灵依赖包”的问题,同时也从根本上避免了在我们的项目里能随意引用显示声明之外的包的问题,并且真正解决了重复包的问题。

monorepo 管理工具除了本文提到的 pnpm ,还有 lernarushbazel等等。

我们团队之所以选用 pnpm ,除了因为 pnpm 的诸多优点,更因为 pnpm 的使用命令和 npm 类似,迁移学习成本低,基本看一遍官方文档就能上手。

这里可以看到我们项目改用 pnpm 之后仓库的大小对比:

右边为pnpm,占用空间少了好几个G

右边为pnpm,占用空间少了好几个G。