扁平化的 node_modules 文件夹名称中(太浪费空间

lxf2023-04-05 10:52:01

文中已经参与「 . 」

pnpm 是 Node.js 的取代包管理器。这是 npm 最直接的替代物,但速度相当快、更有效率。

为何更加高效?如果你组装一个包时,我们将要它储存从你电脑里的全局性存放中,最后我们从创建一个硬链接而非拷贝。换句话说:针对模块每一个版本号,硬盘上只保存一份团本。比如,当使用 npm 或 yarn 时,如果您有 100 个应用 lodash 单肩包,您将于硬盘上有着 100 个 lodash 团本。Pnpm 能够让你节约千兆字节的储存空间!

为什么是 yarn ?

实际上 yarn 只对 npm 的一个小改善。虽然它使组装速度相当快并具有一些非常好的新功能,但它却应用了和 npm 同样的扁平化设计 node_modules 构造。

扁平化的 node_modules 构造带来了很大的难题:

  1. 控制模块能够浏览他们不依附(未进行申明)单肩包 (这极为不科学!)
  2. 扁平化设计依靠的算法比较复杂
  3. 一些包务必拷贝到一个项目node_modules 文件夹名称中(太浪费空间了!)

目前为止,pnpm 具备 yarn 好于 npm 中的所有优势(没错,是所有):

  1. 安全性: 与 Yarn 一样,pnpm 有一个独特文档,其中包括全部已安装文件的校验和,用以在实施其编码以前认证每一个已安装文件的完好性。
  2. 离线状态: pnpm 把所有下载的软件包 tarball 储存在本地注册表文件镜像系统中。当包在本地可以用时,它从来不发出请求。使用这个--offline主要参数,能够完全严禁HTTP 要求。
  3. 速率: pnpm 不但比 npm 快,甚至比 Yarn 快。不论是冷缓存文件或是热缓存文件,它要比 Yarn 快。Yarn 从缓存文件中复制文件,而 pnpm 只从全局性存放中连接他们。

为何?

如同我以前所提到的,pnpm 不容易扁平化设计依靠构造。因而,pnpm 应用的算法能够简单一些。

那样 pnpm 如何构建 node_modules 文件目录,而不是通过扁平化设计呢?要清楚它,我们要回忆一下 node_modules 文件夹名称在 npm@3 以前的模样。在 npm@3 以前,node_modules 构造是可以预测,由于 node_modules 中的每一个依赖项都有各自的 node_modules 文件夹名称,在其中特定了全部依赖项包 .json 。

node_modules
└─ foo
   ├─ index.js
   ├─ package.json
   └─ node_modules
      └─ bar
         ├─ index.js
         └─ package.json

方法有两种棘手的问题:

  • 包常常建立过深的依赖性树,这就导致 Windows 里的文件目录途径太长(直至出差错)
  • 当在不同依赖项过程中需要时,抱被拷贝了好几次

为了能解决这个问题,npm 慎重考虑了 node_modules 构造并给出扁平化设计。应用 npm@3node_modules 构造现在看来像这样的:

node_modules
├─ foo
|  ├─ index.js
|  └─ package.json
└─ bar
   ├─ index.js
   └─ package.json

与 npm@3 不一样,pnpm 尝试处理 npm@2 存在的不足,且不扁平化设计依靠树。在 pnpm 建立的 node_modules 文件夹名称中,全部包都有各自的依赖项组合在一起,但目录树始终也不会像 npm@2 那般深。pnpm 维持全部依存关系平整,但使用软接头把它们组合在一起。


node_modules
├─ foo -> .registry.npmjs.org/foo/1.0.0/node_modules/foo
└─ .registry.npmjs.org
   ├─ foo/1.0.0/node_modules
   |  ├─ bar -> ../../bar/2.0.0/node_modules/bar
   |  └─ foo
   |     ├─ index.js
   |     └─ package.json
   └─ bar/2.0.0/node_modules
      └─ bar
         ├─ index.js
         └─ package.json

尽管这个案例对于一个小程序而言好像太复杂了,但是对于更多的新项目而言,这一构造感觉比 npm/yarn 建立的构造更强。让我们一起看看它为何合理。

最先,你或许已经留意到, node_modules 网站根目录里的包只是一个符号链接。这很好,由于 Node.js 会忽视符号链接并实施真正途径。

次之,全部已下载单肩包则在文件目录里都没有自己 node_modules 文件夹名称。那样 foo 如何找到 bar 呢?使我们看一下包括 foo 包的文件夹名称:

node_modules/.registry.npmjs.org/foo/1.0.0/node_modules
├─ bar -> ../../bar/2.0.0/node_modules/bar
└─ foo
   ├─ index.js
   └─ package.json

如你所看到的:

  1. foo 的依赖项在目录结构中更上一层。
  2. 这俩包都是在 *node_modules 文件夹名称中

foo 可能还需要 bar,由于 Node.js 在目录结构中搜索控制模块直至硬盘的网站根目录。foo 还可以 requirefoo,因为他就在那 node_modules 中。

尝试一下吧

你只要根据 npm 组装 pnpm:实行 npm install -g pnpm。那样以后就不要用 npm 啦。