安装pnpm:下一代JS软件包管理器,比npm和yarn快2倍。
介绍pnpm,JS软件包管理器三人组中的小兄弟。 我将尝试解释pnpm如何比npm和yarn工作得更快,并组织如何安装和使用它。
1. 介绍pnpm
pnpm的官方主页:https://pnpm.io/zh/ (opens in a new tab)
pnpm是新一代的JS包管理器,旨在克服传统JS包管理器的性能限制。 pnpm这个名字是Performant npm的缩写,从这个名字就可以看出它是为高效性能而设计的。
使用它与使用其他软件包管理器几乎是一样的。
它以package.json
文件为基础工作,几乎可以取代npm和yarn的所有功能。
命令行ming的构建更像yarn。
2. pnpm的三个优势
使用pnpm有三个主要优势。
它可以节省磁盘空间,使依赖性安装更快,并更有效地组织node_modules
目录结构。
让我们一个一个地看。
2.1. 更少的磁盘使用
pnpm之所以能做同样的事情而使用更少的磁盘空间,是因为它使用了一个叫做 content-addressable storage(CAS) 的中央存储库。 当你用pnpm安装一个软件包时,所有的软件包都存储在这个存储库中。 而每一个使用pnpm的项目都会从这个存储库中获得它所需要的软件包。
例如,如果我用npm创建了三个React项目,React包将被安装在每个项目的node_modules
目录中。
这意味着我的机器上安装了3个相同的包。
然而,如果我使用pnpm,在CAS仓库中只安装了一个react包,所有三个项目都共享这个包。
解释一下CAS如何与pnpm一起工作:
如果你需要的软件包有不同的版本,CAS 仓库会有效地处理这个问题。 它只下载和存储每个版本中已经改变的文件。 这类似于Docker中的依赖性管理算法。
在JS/TS开发中,很容易在任何项目中发现重复的包,或者同时依赖多个包的包。 在这些情况下,pnpm所节省的磁盘空间可能是相当大的。
上面是用pnpm安装一些软件包时的进度日志输出。最后一行的每个数字表示
resolved
:需要的软件包总数reused
:在resolved
中已经安装在CAS仓库的软件包数量downloaded
:在resolved
中新下载的软件包数量added
:作为结果添加到项目中的软件包的数量。
在上述情况下,由于没有新的软件包需要下载,所以没有磁盘或网络的使用,这应该可以加快安装时间。 如果软件包安装在CAS仓库中,你甚至可以在离线状态下将其添加到项目中。
2.2. 更快的依赖包安装
pnpm能够更快地进行依赖性安装的第一个原因是上面提到的CAS仓库。 首先,它不会重新安装已经在仓库中的包,而且当一个版本升级时,需要下载的文件明显减少,所以难怪它的速度更快。
其次,pnpm支持软件包的并行安装。
JS软件包管理器遵循三步程序来安装依赖关系: [确定你需要的依赖项->下载->编译包]。 在npm的情况下,所有的包都必须在完成一个步骤后才能进入下一个步骤。 由于 pnpm 假设软件包之间互不干扰,每个软件包都可以单独完成第三步。
在下图中,横轴是时间,纵轴是每个软件包。 即使所有的软件包都没有完成前一步,先完成的那一个也会进入下一步,使整个安装过程更快。
2.3. 更严密、更高效的node_modules目录
上面提到的三个依赖性安装步骤中的第一个,即确定所需的依赖性,被称为依赖性解析。 在这个步骤中,软件包管理器会跟踪这个项目使用的软件包和它们所依赖的软件包,并计划将它们全部安装。
直到npm第2版,我们曾经在这个阶段安装所有的包,这造成了两个问题。
首先,如果 包A
和 包B
都有 包C
作为依赖,它们会被安装两次,尽管它们是重复的。
这是不必要的重复。
第二,每个包的node_modules
目录都是夹着尾巴安装的。
这被称为nested node_modules,像下面的目录结构。
▾ node_modules
▾ package A
▾ node_modules
▸ package C
▾ package B
▾ node_modules
▾ package C
▸ node_modules
在npm 3+和yarn中,我们使用flat node_modules结构来解决这个问题。
这是一种在项目中安装node_modules
下的所有软件包的方法,不管它们的依赖深度如何。
▾ node_modules
▾ .bin
▾ accepts
▾ array-flatten
...
▾ etag
▾ express
这种扁平化的结构可以防止重复安装,但也引入了另一个问题。
这就是任何我作为依赖关系安装的软件包都可以在这个项目中使用,即使它没有通过package.json
明确安装。
例如,我正在使用版本1的package S
,我把它作为package A
的依赖项安装,而没有把它放在package.json
中、
如果我们需要升级到package S
的第2版,会发生什么?
因为我们没有跟踪package S
,所以不可能自动升级,导致运行时错误。
PNPM可以防止这种情况。
用pnpm创建的node_modules
中的包文件都是与CAS仓库中的实际文件的符号链接或硬链接,所以它们可以自由重组和优化。
这使得我们可以解决重复包的问题,而不必使用扁平结构,并且只限制访问那些我们明确安装的包。
3. 中级组织
正如你所看到的,pnpm的效率是传统软件包管理器的两倍多,仅仅是通过使用CAS仓库尽可能地消除了重复的东西。 在这个过程中,我们也获得了很多的稳定性。
现在让我们快速看看如何安装和使用pnpm。
4.如何安装
建议你使用npm全局安装pnpm。 它可以用一个简单的命令来安装。当然它也可以在Windows上使用。
npm install -g pnpm
执行的结果:
也可以用Corepack for Node.js来安装,但这仍是实验性的,所以我不会描述它。
5. 如何使用它
使用方法与npm和yarn几乎相同。
5.1. 管理项目中的包
-
pnpm init
:启动一个新项目,该项目将由pnpm管理。 -
pnpm install
:为项目安装预先建立的依赖包列表。 -
pnpm add [package_name]
: 向你的项目添加一个或多个新包。 -
pnpm exec [package_name]
: 从命令行运行你在项目中安装的软件包。 -
pnpm run [script_name]
:运行项目中指定的npm脚本。
5.2. 全局软件包管理
-
pnpm dlx [package_name]
:下载并临时运行一个包,而不安装它。 -
pnpm create [package_name]
:使用支持创建的软件包的启动包创建一个新项目。 -
pnpm add -g [package_name]
:添加一个全局软件包。 -
pnpm list -g
:列出所有已安装的全局软件包。
更多命令请输入pnpm
。
