为什么 pnpm 比 npm 更快且更省空间?

2024年1月1日

💎 加入 E+ 成長計畫 如果你喜歡我們的內容,歡迎加入 E+,獲得更多深入的軟體前後端內容

身为前端开发者,你大概一定听过 npm 这个套件管理工具,可能也听过社群许多人会用的 yarn,以及过去两年热门的 bun。但其实还有一个叫 pnpm 的套件管理工具,是在 bun 出来之前,受到许多开发团队亲赖的。这篇文章我们来聊聊 pnpm。

在 pnpm 的官网中是用 Fast, disk space efficient package manager 来介绍 pnpm 的。可以看到,这边强调的是两个特点,一个是在时间维度上快,另一个是在空间维度上有效率。

先来讲快这一点,之所以 pnpm 比起 npm 或者 yarn 来得快,是因为 pnpm 在设计上,共享了依赖,这可以避免重复下载何解压缩已经被处理过的套件,因此在多个不同套件都有相同依赖的状况下,pnpm 会快很多。除此之外,pnpm 也做了本地快取,这能够减少对网路的依赖;在有快取的状况下,即使网路速度慢,如果命中本地快取,一样可以快速完成套件安装。

接着来讲空间上的节省,因为 pnpm 有全局储存 (global store) 的机制,这能有效避免重复储存相同的依赖,因此如果你使用的多个套件有重复依赖,最终这些相同的依赖,都只会在硬碟中存一次,这大幅度降低依赖在硬碟中占据的空间。对比起来,npm 与 yarn 都会在每一个不同的专案复制一份,因此会占用比较多空间。

要理解 pnpm 在依赖结构设计的巧妙上,我们要先懂 Node.js 是如何找到某个依赖的:

  • 首先 Node.js 会先找自己的模组 (例如 fs),这部分不需要额外路径解析

  • 如果不是 Node.js 内建模组,它会从 node_modules 底下开始找,如果没有 node_modules,则会从目前的档案目录中,逐一遍历直到找到最近的 node_modules 然后从中找寻某个模组

  • 如果找不到,就会继续遍历直到找到,如果遍历完整个目录还是找不到,就会抛出错误

在 pnpm 的设计下,当 Node.js 要开始查找模组时,在 node_modules 底下,大家可能会看到右箭头的符号,这个右箭头是指某个连链接 (link),这个链接会指向上面有提到的全域储存 (global store),所以可以理解成,当 Node 要找该模组时,pnpm 会跟 Node 说去全域的某个位置可以找到。

而这个全域储存的位置,就是在 node_modules 底下的 .pnpm 资料夹中,只有在这个资料夹当中的,是真正的档案,其他的都只是一个指针 (pointer),会指向这个真正存的地方。这样一来,就可以避免同样的依赖被复制一份并且重复存

从 pnpm 的设计可以看到,其实在前端的领域,把资料结构学好,是很有价值的,当换了一种设计,就能大幅度减少使用的空间~

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們