JavaScript包管理器NPM 与 YARN 与 PNPM的区别

文章发布于 2023-05-02

包管理器是帮助程序员和开发人员安装、更新和卸载代码、库或其他软件的包的软件工具。有许多用于各种编程语言的包管理器,例如 JavaScript 的 NPM 和 Ruby 的 GEM。

包管理器通常使用元数据来确定可用的包版本,并且每个版本包管理器的依赖关系因它们安装和更新的自动化软件的类型而异。

示例包括 apt-get、DNF (Fedora/Red Hat)、Pacman (Arch Linux) 和 npm (Node.js)。任何用户都可以从这个公共池中添加或删除包。包通常从远程服务器检索,但也可以在本地安装。

什么是包管理器

包管理器是处理计算机软件包的安装、升级和删除的软件。

包管理器将包存储在硬盘或网络驱动器的中心位置。它允许多个用户共享包的单个副本。

包管理器,如 npm install 和 yarn add,通常是基于 CLI 的。通常,JavaScript应用程序有许多依赖项,这些依赖项由包管理器管理。

Node 默认使用 NPM。但是,NPM 没有一些高级功能非常适合更高级的应用程序,或者在安装包或解决包依赖关系时速度很慢。

Yarn 和 PNPM 是社区制作的包管理器,它们的存在就是为了解决上述问题。在过去的几年里,纱线变慢了,但今天它可能是最受欢迎的选择。

在包管理领域,PNPM 是最新出现的玩家,它使安装和升级包的速度更快。

npm 、yarn 和pnpm比较

NPM 是最初由Node.js项目开发的 JavaScript 包管理器。它使开发人员能够更轻松地在不同项目之间共享代码,并在自己的项目中使用其他人的代码。

Yarn 是 JavaScript 的包管理器,由 Facebook 开发。它快速、可靠且安全。

PNPM 是一个新的 JavaScript 包管理器,它构建在 npm 之上,以简化节点应用程序中包的安装过程。PNPM 是 NPM 的替代品。它遵循与 NPM 相同的原则,但它具有一些附加功能,使其比其前身更强大。

1 性能和磁盘效率

npm:与 Yarn 和 PNPM 相比,它有点慢。

yarn: Yarn 使用相同的扁平化 node_modules 目录,但在速度和并行安装包方面与 NPM 相当。

pnpm: PNPM比 NPM快 3 倍,效率更高。使用冷缓存和热缓存,PNPM 比 Yarn 更快。


Pnpm 只是从全局存储中链接文件,而 yarn 从其缓存中复制文件。软件包版本永远不会在磁盘上多次保存。

pnpm 的算法没有使用扁平化的依赖树,这使得它更容易实现、维护,并且需要更少的计算。

这是 NPM 3 及更早版本中使用的方法,但嵌套存在问题,因此必须为每个依赖它们的包复制多次包。

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

与 NPM 相比,PNPM 通过硬链接和符号链接解决了上述问题。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 还可以节省大量空间。

2 安全

NPM:由于 npm 处理坏包的方式,一些安全漏洞直接影响了许多项目。


YARN:存储在 yarn.lock 中的校验和一直被 Yarn Classic 和 Yarn Berry 使用。Yarn 还可以防止您安装恶意软件包;如果检测到不匹配,安装将中止。


PNPM:与 Yarn 类似,PNPM 也使用校验和,除了使用校验和之外,pnpm 还在执行代码之前验证其代码的完整性。

3 Monorepository 支持

Monorepository 由多个独立的代码存储库组成,所有这些代码存储库都位于一个存储库中,以避免管理多个存储库。

NPM: NPM 包管理器通过各种 CLI 命令提供 monorepo 支持来管理多个包。但是,与其他包管理器不同,它不支持高级过滤或多个工作区。


YARN:它还提供 monorepo 支持作为功能工作区。在工作区功能可用之前,使用第三方应用程序Lerna是在多包项目中使用包管理器的唯一方法。


PNPM: NPM 的分身问题只能用 PNPM 来解决。Monorepos 有时会受到分身的困扰,因此 PNPM 在这方面具有优势。

4 安装工作流程

正如我之前所说,必须首先在本地安装包管理器和 CI/CD。

NPM:它是世界上最大的包注册中心之一,应该与 Node.js 一起安装。它使用package.jsonpackage.lock.json文件。

要下载软件包,请打开终端并输入以下命令:

npm install "package_name"

默认情况下,npm 会创建一个名为 package.json 的文件夹,并且每当您使用 npm 下载一个包时,该文件夹就会放置在这里。


YARN:为了解决 NPM 的问题,开发了 YARN。它提供了许多后来与 npm 合并的新功能,例如带有版本的锁定文件、缓存等。

Yarn 使用package.jsonand yarn.lock files

您可以通过不同的方式安装 Yarn - 使用 npm 作为 npm 包:

npm install -g yarn

PNPM:您可以使用 npm 包轻松安装 PNPM。

npm install -g pnpm
5 项目结构

一旦安装过程结束,它将生成可以轻松查看的相应文件,并且所有重要的元信息都存储在名为 package.json 的文件中。

NPM:使用 npm install 一个 package-lock.json 并生成一个 node_modules 文件夹。您可以手动将 .npmrc 配置文件放在根级别。

.
├── node_modules/
├── .npmrc
├── package-lock.json
└── package.json

YARN:这还将创建 yarn.lock 文件和 node_modules 文件夹。您还可以使用**.yarnrc文件配置您的纱线;Yarn Classic 也承认.npmrc**文件。

.
├── .yarn/
│   ├── cache/
│   └── releases/
│       └── yarn-1.22.17.cjs
├── node_modules/
├── .yarnrc
├── package.json
└── yarn.lock

除了 .yarn/cache/ 之外,还可以使用其他存储 yarn 经典版本的位置(.yarn/releases/)。


PNPM:与 NPM 不同,PNPM 不会创建扁平的依赖关系树。在 node_modules 中,所有东西在 package.json 中都有自己的 node_modules 文件夹,并且每个依赖项都在 package.json 中精确指定。在 npm 版本 3 之前,node_modules 结构是可预测的。

这种方法的问题是双重的:

  1. windows 经常遇到由依赖树太深的包引起的长目录路径问题
  2. 多次复制包以满足多个依赖项

PNPM 解决了这个问题而没有展平依赖树。每个包的依赖项都在一个 node_modules 文件夹中组合在一起,并且符号链接用于将依赖项组合在一起,因此目录树是扁平的。

.
├── node_modules/
│   └── .pnpm/
├── .npmrc
├── package.json
└── pnpm-lock.yml

使用 安装依赖项后会创建一个 package.json 文件pnpm i,还会node_modules生成一个文件夹,但由于其内容可寻址存储方法,它的结构将与 npm 和 yarn 完全不同。


例子:

node_modules
└── .pnpm
    ├── bar@1.0.0
    │   └── node_modules
    │       └── bar -> <store>/bar
    │           ├── index.js
    │           └── package.json
    └── foo@1.0.0
        └── node_modules
            └── foo -> <store>/foo
                ├── index.js
                └── package.json

结果

包管理器目前处于良好状态。几乎所有主要的包管理器都实现了功能对等。引擎盖下存在差异。

虽然 PNPM 与 NPM 有一些相似之处,但它们管理依赖关系的方法却大不相同。PNPM 的方法提供了更好的性能和更好的磁盘空间效率。

很快,Yarn Classic 可能会停止支持,因为它被视为遗留软件。

作为最新的包管理器竞争者,Yarn Berry PnP 仍未充分发挥其潜力来彻底改变包管理领域。

依赖关系在 JavaScript 应用程序中很常见。包管理器通常用于管理这些依赖项。默认情况下,节点使用 NPM。

尽管 NPM 缺少一些高级功能,但它在解决包依赖和安装包方面做得很好。