Javascript
开发环境配置
Pnpm: 软件包管理器

安装pnpm:下一代JS软件包管理器,比npm和yarn快2倍。

介绍pnpm,JS软件包管理器三人组中的小兄弟。 我将尝试解释pnpm如何比npm和yarn工作得更快,并组织如何安装和使用它。

1. 介绍pnpm

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工作原理的解释

如果你需要的软件包有不同的版本,CAS 仓库会有效地处理这个问题。 它只下载和存储每个版本中已经改变的文件。 这类似于Docker中的依赖性管理算法。

在JS/TS开发中,很容易在任何项目中发现重复的包,或者同时依赖多个包的包。 在这些情况下,pnpm所节省的磁盘空间可能是相当大的。

pnpm进度日志

上面是用pnpm安装一些软件包时的进度日志输出。最后一行的每个数字表示

  • resolved:需要的软件包总数
  • reused:在resolved中已经安装在CAS仓库的软件包数量
  • downloaded:在resolved中新下载的软件包数量
  • added:作为结果添加到项目中的软件包的数量。

在上述情况下,由于没有新的软件包需要下载,所以没有磁盘或网络的使用,这应该可以加快安装时间。 如果软件包安装在CAS仓库中,你甚至可以在离线状态下将其添加到项目中。

2.2. 更快的依赖包安装

pnpm能够更快地进行依赖性安装的第一个原因是上面提到的CAS仓库。 首先,它不会重新安装已经在仓库中的包,而且当一个版本升级时,需要下载的文件明显减少,所以难怪它的速度更快。

其次,pnpm支持软件包的并行安装。

JS软件包管理器遵循三步程序来安装依赖关系: [确定你需要的依赖项->下载->编译包]。 在npm的情况下,所有的包都必须在完成一个步骤后才能进入下一个步骤。 由于 pnpm 假设软件包之间互不干扰,每个软件包都可以单独完成第三步。

在下图中,横轴是时间,纵轴是每个软件包。 即使所有的软件包都没有完成前一步,先完成的那一个也会进入下一步,使整个安装过程更快。

并行安装pnpm包

并行安装pnpm包的例子(source (opens in a new tab)

2.3. 更严密、更高效的node_modules目录

上面提到的三个依赖性安装步骤中的第一个,即确定所需的依赖性,被称为依赖性解析。 在这个步骤中,软件包管理器会跟踪这个项目使用的软件包和它们所依赖的软件包,并计划将它们全部安装。

直到npm第2版,我们曾经在这个阶段安装所有的包,这造成了两个问题。

首先,如果 包A 包B 都有 包C 作为依赖,它们会被安装两次,尽管它们是重复的。 这是不必要的重复。

第二,每个包的node_modules目录都是夹着尾巴安装的。 这被称为nested 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下的所有软件包的方法,不管它们的依赖深度如何。

flat 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

执行的结果: 用npm安装pnpm

也可以用Corepack for Node.js来安装,但这仍是实验性的,所以我不会描述它。

5. 如何使用它

使用方法与npm和yarn几乎相同。

5.1. 管理项目中的包

  • pnpm init:启动一个新项目,该项目将由pnpm管理。 pnpm init的例子

  • pnpm install:为项目安装预先建立的依赖包列表。 pnpm install的例子

  • pnpm add [package_name]: 向你的项目添加一个或多个新包。 pnpm add的例子

  • pnpm exec [package_name]: 从命令行运行你在项目中安装的软件包。 pnpm exec的例子

  • pnpm run [script_name]:运行项目中指定的npm脚本。 pnpm run example pnpm run dev result

5.2. 全局软件包管理

  • pnpm dlx [package_name]:下载并临时运行一个包,而不安装它。 phpm dlx 示例

  • pnpm create [package_name]:使用支持创建的软件包的启动包创建一个新项目。 pnpm create的例子

  • pnpm add -g [package_name]:添加一个全局软件包。 pnpm add -g Example

  • pnpm list -g:列出所有已安装的全局软件包。 pnpm list -g Example

更多命令请输入pnpm

pnpm命令列表

copyright for Javascript pnpm install

© 2023 All rights reserved.