工欲善其事,必先利其器 -- pnpm

2022/01/17 Config 共 1995 字,约 6 分钟

众所周知,前端项目的 node_modules,是一个深渊,项目稍大一些,那所安装的依赖,轻轻松松上百个,存储空间几百 MB,再大单位就是 GB 了,简直离谱。用命令统计一下文件数量,几万个都算是少的。

于是,电脑上项目数量多了的话,仅仅是这个 node_modules,就占据了不少的空间,且不少都是重复性的依赖安装包!那么有什么方式可以优化这个呢?

包管理器

大家最常使用的包管理器,那应该是 npmyarn 了吧,对于这两者的历史与介绍,这里就不做展开了,下面说说今天的主角:pnpm官网传送门

pnpm - 是什么

一个包管理器。

slogan:快速的,节省磁盘空间的包管理器(Fast, disk space efficient package manager),从而我们可以了解到,特点是一个能够节省磁盘空间的包管理器,唔,npm 和 yarn 遇到对手了。至于快速这个特点,我们稍后再看,毕竟,节省磁盘空间这个特点看起来很靓哦。

pnpm - 解决了什么,怎么做到的

安装

刚刚得知,相比其他的包管理器,pnpm 一个很大的特点就是能够节省磁盘空间,哇哦,这不就是我们前面说到的,node_modules 它这个磁盘地狱问题吗,如果使用 pnpm 能解决这个问题,单单冲这一点,那也得冲一波啊,这就去看看。

惯例,先看文档,了解安装跑 DEMO 三部曲走一下。(省略若干

OK,现在电脑上已经安装了最新版的 pnpm,-v 一下,输出 6.24.4

跑项目对比

现在我们用 vite 初始化一个 vue3 项目,分别使用 pnpm 和 yarn 作为包管理器,从文档和下图可以得知,在 pnpm 中,如果一些依赖已经安装过,则会存在电脑中,再次在项目中使用时,是硬连接到项目中,所以在速度上,比 yarn 号称快的包管理器还要快,唔。

那我们在看一下两者的 node_modules,有何区别。

OK,经过查看,在文件大小方面,两者只有 1MB 之差??不是说好的,pnpm 包是全局存储,为何 node_modules 还是使用了磁盘空间?欺负老实人的吗,让我看看。

原来硬连接是这回事啊(不明觉厉)官方回答 FAQ

pnpm 在 install 时,是会创建项目所需依赖到全局存储依赖包的硬连接。而硬连接指向磁盘上原始文件所在的同一位置。因此,当我们查看 A 项目的 node_modules 中的 foo 依赖,和查看 B 项目的 node_modules 中的 foo 依赖,看到都是 1MB,但实际上都是磁盘上同一个文件,所以总磁盘空间还是 1MB。举个例子:某张银行卡同时绑定了微信和支付宝,卡内有一万元,这时候通过微信查看,唔,有一万元,通过支付宝查看,唔也有一万元,但是,我们不会认为,卡里有两万元吧。

总之,pnpm 革命性的节约磁盘空间,是通过链接这种方式,做到的,至于一些复杂的情况如嵌套依赖,版本管理等这些,个人理解有限,怕有所误解,就建议阅读官方文档进行学习了解了。

在上图中,pnpm 和 yarn 还有一个不同的地方,是什么呢?是 node_modules 目录下文件的不同。前者目录下似乎只有 package.json 文件所声明的依赖,而后者呢,则是平铺了 node_modules,即,所有的依赖都会在这一层级。

关于这一点的详细不同,可以参考 官方的博客文章

但对于用户来说,这样做有一个潜在的好处,那就是避免幽灵依赖!

幽灵依赖

幽灵依赖,即没有在 package.json 中声明依赖,但在代码中呢,可以使用的依赖。

在项目中,我们在 package.json 中声明了 A 依赖,然后 A 依赖同时依赖 B 依赖,那么使用 yarn or npm 进行安装时,由于两者都是平铺 node_modules,那么在代码中,我们竟可以使用 B 依赖,尽管,package.json 中,未曾声明 B 依赖!

之所以说是潜在问题,即未来某时,我们项目不再使用 A 依赖了,或者 A 依赖升级,不再需要 B 依赖了,那么代码中,那个使用 B 依赖的地方,就会出问题。再者,本着版本管理规范的说法,在项目中所需要的依赖,也是要在 package.json 中进行声明的。

所以,pnpm 这种非平铺的方式,在源头就避免了幽灵依赖这种问题。

pnpm - 未来可期

为何这样说呢,在现在一个前端项目,动则上 GB 的存储空间下,磁盘空间已经是一个需要关注的资源了,再加上服务器多项目部署,那无论是速度还是空间,都是一个性能点。因此,pnpm 的出现,就解决了这些痛点。

pnpm 是 2015 年诞生的,迄今为止也有六七年的发展了,其迭代版本已经稳定到 6.24,那么在项目开发中,是一个可以放心使用的包管理器了。这不,尤大的 Vue 全家桶,都已经在使用 pnpm 作为官方包管理器。

再说,没有完美的事物,只有趋近完美。你不用我不用,就算有 bug 也没人知。所以有 bug 不怕,可以在其 GitHub 上提 issues 或者参与贡献!

结语

很久之前我就有想过多项目重复的依赖,为何不用连接呢,但我只是想想,没想到 pnpm 就是这样的,真的挺好。

文档信息

Search

    Table of Contents