pnpm 是又一个 Node.js 包管理工具。它能够替换 npm, 并且 npm 更快更高效。html
能有多快? 3 倍! 能够在这里查看 benchmarks 。node
为何更高效? 当你安装一个软件包,咱们把它保存在你的机器上的一个全局存储目录中,而后咱们建立一个硬连接而不是复制。 对于模块的每一个版本,只会有一个副本保存在磁盘上。 例如,当使用 npm 或 yarn 时,若是有 100 个使用 lodash 的项目,你的磁盘上就会有有 100 份 lodash 的拷贝。pnpm 能帮助您节省千兆字节的磁盘空间!git
Yarn
老实说,当 Yarn
开始公开时,我真的很失望。 几个月来我一直在为 pnpm
做出重大贡献,并且没有任何关于 Yarn 的消息。 有关其发展的信息是不公开的。github
几天以后,我意识到 Yarn 只是 npm 的一个小小的改进。 尽管它使得安装速度更快,而且具备一些不错的新功能,可是它使用了与 npm 相同的扁平 node_modules 结构(从版本 3 开始)。算法
扁平化的依赖关系树带来了一系列的问题:shell
此外,还有一些 Yarn 不打算解决的问题,如磁盘空间使用问题。 因此我决定继续把时间花在 pnpm 上,并取得了巨大的成功。 截至目前(2017 年 3 月),pnpm 具备 Yarn 超过 npm 的全部附加功能:npm
正如我前面提到的,pnpm 不会拍平依赖关系树。 所以,pnpm 使用的算法能够更容易! 这就是为何只有一名开发人员可以跟上 Yarn 的几十位贡献者的步伐。json
那么,若是不依靠拍平的方式,pnpm 如何构造 node_modules 目录呢? 为了理解它,咱们应该回忆在 npm 版本 3 以前 node_modules 文件夹看起来是怎样的。在 npm@3 以前,node_modules 结构是可预测和干净的,由于 node_modules 中的每一个依赖项都有本身的 node_modules 以及所包含依赖关系的 package.json 文件。缓存
node_modules └─ foo ├─ index.js ├─ package.json └─ node_modules └─ bar ├─ index.js └─ package.json
这种方法有两个严重的问题:安全
为了解决这些问题,npm 从新思考了 node_modules 结构,并提出了扁平化。 在 npm@3 中,node_modules 的结构如今看起来像这样:
node_modules ├─ foo | ├─ index.js | └─ package.json └─ bar ├─ index.js └─ package.json
有关 npm v3 依赖关系解析的更多信息,请参见 npm v3 依赖关系解析。
与 npm@3 不一样,pnpm 试图解决 npm@2 所具备的问题,而不是将依赖关系树展平。 在由 pnpm 建立的 node_modules 文件夹中,全部的软件包都有本身的依赖关系,可是目录树永远不会像 npm@2 那么深。 pnpm 保持全部依赖关系平坦,但使用符号连接将它们组合在一块儿。
-> - a symlink (or junction on Windows) 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
要查看实例,请访问 示例 pnpm 项目。
虽然这个例子对于一个小项目彷佛太复杂了,可是对于更大的项目来讲,结构看起来比 npm / yarn 建立的结构要好。 让咱们看看为何它不错。
首先,您可能已经注意到,node_modules 根目录下的包只是一个符号连接。 这很好,由于 Node.js 忽略符号连接并执行实际路径。 因此 require('foo')会执行文件 node_modules/.registry.npmjs.org/foo/1.0.0/node_modules/foo/index.js
而不是 node_modules/foo/index.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
如您所看到的
foo
的依赖关系(只有 bar
)被安装,但在目录结构中的一级。foo
能够引入 bar
,由于 Node.js 在目录结构中查找模块直到磁盘的根目录。 并且 foo
也能够引入 foo
,由于它在一个名为 node_modules 的文件夹中(没错,这正是一些软件包所作的)。
只需经过 npm 安装 pnpm:npm install -g pnpm。 只要你想安装一些东西,就用它来代替 npm:pnpm i foo。
您也能够在 pnpm GitHub repo 或 pnpm.js.org 中阅读更多信息。 您能够关注 pnpm on Twitter,或者在 pnpm Gitter Chat Room 寻求帮助。