细说包管理器yarn和npm

在过去,一个简单的文本编辑器就足以让开发人员创建和管理大部分项目。但从那以后,WEB发生了翻天覆地的变化,如今,即使是一个相当简单的项目,通常也会有成百上千个带有复杂嵌套依赖关系的脚本,如果没有自动化工具,这些脚本根本无法有序的管理,这时就需要包管理器。

包管理器是一种以各种方式自动处理项目依赖关系的工具。例如,在包管理器的帮助下,可以安装、卸载、更新和升级包,配置项目设置、运行脚本等等。所有复杂和乏味的工作都由包管理器完成,让开发人员专注于编码。

npm 是Node的包管理器,它于2010年发布,开启了web开发的新时代。在此之前,项目依赖库都是手动下载和管理的,npm 是把WEB开发推向了一个更高的阶段。

npm 主要做三件事:

  • 一个用于管理 npm 体验各个方面的网站
  • 用于访问广泛的 JavaScript 包公共数据库的注册表
  • 用于通过终端与 npm 交互的命令行界面(CLI)

然而,大多数人谈论 npm 时,通常指的是最后一个 CLI 工具。它作为默认包管理器与每个新的 Node版本一起发布。

yarn 代表另一个资源谈判者。yarn 包管理器是 npm 的一个替代方案,由Facebook于2016年10月发布。yarn最初的目标是处理npm的缺点,比如性能和安全问题。yarn很快被定位为一个安全、快速、可靠的JavaScript依赖管理工具。

但是 npm 团队吸取了教训,并通过实现缺失的功能迅速填补了 npm 的空白。

下面来看一个时间线:

  • 2010年:发布了支持Node的npm。
  • 2016年:Yarn发布。它展现了比npm更好的性能。它也会生成yarn.lock 文件,使共享和精确复制回购更容易和可预测。
  • 2017年:NPM 5发布。它提供自动生成的包锁 package-lock.json 文件应对 yarn.lock
  • 2018年:NPM 6的发布提高了安全性。现在,npm在安装依赖项之前会检查安全漏洞。
  • 2020年:Yarn 2和npm 7发布。这两个包都有很棒的新特性。
  • 2021年:Yarn 3发布了各种改进。

如今,这两种包管理器在包管理竞赛中并驾齐下,提供了相似的特性和功能。但仍有一些差异,有助于选择使用。

安装比较

从 npm 和 yarn 的安装过程开始来进行比较。

安装包管理器

正如上面提到的,npm 是预先安装在 Node 中的,所以一般不需要手动安装 npm。

相反,yarn 需要显式安装,首先,需要全局安装 yarn:

npm install -g yarn

然后,可以通过在项目中设置所需的版本,在每个项目的基础上使用它。通过在项目的根目录中运行 yarn set version 命令来设置所需要的版本:

yarn set version berry

berry 就是要设置的版本号。如果想更新到最新版本,运行:

yarn set version latest

使用 yarn,可以为每个项目使用不同的版本。而对 npm 要实现同样的需求,则需要安装 nvm(Node版本管理器)。

安装项目依赖

现在,就来看看如何安装项目依赖项。 当运行 npm install 时,依赖项会依次安装,终端中会输出详细的安装日志,不过阅读性不好。

使用 yarn 安装包,运行 yarn 命令。yarn 是并行安装包的,这也是它比 npm 快的原因之一。如果正在使用 yarn 1,将看到 yarn 输出的安装日志比较简洁,阅读性也比较好。为了方便阅读,它们以树状排列。但是这在版本2和版本3中有所改变,其中的日志不是那么直观和可读。

到目前为止,已经看到 npm 和 yarn 有不同的安装包命令。

命令比较

npm 和 yarn 很多命令是一样的,但也有许多不同的命令。先来看看相同的命令:

  • npm init | yarn init:创建一个新包
  • npm run | yarn run:运行 package.json 中定义的脚本
  • npm test | yarn test:测试一个包
  • npm publish | yarn publish:发布一个包
  • npm cache clean | yarn cache clean:从缓存文件夹中删除所有数据

这些命令使两个管理器之间的切换变得容易,但有一些不同的命令可能会导致混淆。

  • npm install | yarn:安装依赖
  • npm install [package] | yarn add [package]:安装一个包
  • npm install --save-dev [package] | yarn add --dev [package]:安装包作为开发依赖项
  • npm uninstall [package] | yarn remove [package]:卸载一个包
  • npm uninstall --save-dev [package] | yarn remove [package]:卸载开发依赖包
  • npm update | yarn upgrade:更新的依赖关系
  • npm update [package] | yarn upgrade [package]:更新包

yarn 还有一些独特的命令,这些命令在 npm 下没有相同的。例如,why 命令显示需要一个包的原因:它可能是一个依赖项、一个本地模块或一个项目依赖项。

速度和性能

每当 yarn 或 npm 需要安装包时,它们都会执行一系列任务。在 npm 中,这些任务是按包顺序逐个执行安装的,这意味着它会等待一个包完全安装,然后再继续下一个。相比之下,yarn 是并行执行这些任务,在性能上有显著的提高。

虽然这两种管理器都提供缓存机制,但yarn似乎做得更好一些。通过实现零安装模式,它几乎能够在短时间内安装包。它缓存每个包并将其保存在磁盘上,所以在下一次安装这个包时,甚至不需要有互联网连接,因为包是从磁盘离线安装的。

尽管yarn有一些优势,但 yarn 和 npm 在它们的最新版本中的速度相当,所以现在算不分伯仲。

安全性比较

对 npm 的主要批评之一是在安全性方面,以前的 npm 版本有几个严重的安全漏洞。然而从版本 6 开始,npm 在安装过程中审核软件包并显示是否发现任何漏洞。可以通过对已安装的软件包运行 npm audit 来手动执行此检查,如果发现任何漏洞,npm 会给出相应的安全建议。如发现有安全漏洞,可以运行 npm audit fix 来修复包漏洞。

在安全性上,yarn 和 npm 都使用加密哈希算法来确保包的完整性。

功能比较

就如上面介绍的命令一样,一些特性是 npm 和 yarn 共有的,但也有一些区别,下面就来介绍主要的区别。

生成的锁定文件

package.json 文件中,npm 和 yarn 都在其中跟踪项目的依赖项,版本号并不总是准确的,相反,可以定义一系列版本。这样,可以选择一个包的主版本和小版本,但允许npm安装可能修复一些bug的最新补丁。

在语义版本控制的理想状态下,补丁版本不会包含任何破坏性的更改。但显示总是和理想有区别,导致真实情况下并非如此。npm 采用的策略可能会导致两台机器以相同的 package.json 文件结束,但安装了不同版本的包,这就埋下了可能产生bug的问题。

为避免包版本不匹配,确切安装的版本被固定在包锁定文件中,每次添加模块时,npm 和 yarn 分别创建(或更新)一个 package-lock.json 和 yarn.lock 文件。

使用工作空间

工作区允许拥有一个 monorepo 来管理跨多个项目的依赖项,这意味着有一个单一的顶级根包,其中包含多个称为工作区的子包。

远程运行脚本

npx 命令用于从 ./node_modules/.bin 运行脚本。它还允许从 npm 注册表中执行包,而无需将它们安装在项目依赖项中。例如,可以通过运行以下命令来创建一个新的 React 应用程序:

npx create-react-app my-app

在 yarn 中,可以使用等效的 dlx 命令获得相同的结果:

yarn dlx create-react-app my-app

下面将介绍 yarn 独有的功能。

零安装

零安装将缓存存储在项目目录中的 .yarn 文件夹中。当使用 yarn 或 yarn add  等命令时,yarn 会创建一个 .pnp.cjs 文件,此文件包含 Node 用于加载项目包的依赖关系层次结构。因此,几乎可以在零时间访问它们。

即插即用

即插即用是另一种安装策略,yarn 没有生成 node_modules 目录并将解析留给 Node,而是生成单个 .pnp.cjs 文件,该文件将包映射到它们在磁盘上的位置及其依赖项列表。这个特性可以导致更快的项目启动、更好的优化依赖树、更快的安装时间,当然也不需要 node_modules 文件夹。

Licenses

yarn 包含一个内置的许可证检查器,可在开发应用程序时在不同场景中使用。

选择哪个包管理器

上面已经讨论了 npm 和 yarn 的各种相似和不同之处,但是还没有确定哪一个更好,应该选择哪一个,但是还是那句话,适合的团队或者项目的才是最重要。

下面给出一个推荐的建议:

  • 选择 npm :如果对当前的工作流程感到满意,不想安装额外的工具,并且没有很多磁盘空间。
  • 选择 yarn :如果想要一些很棒的功能,比如即插即用,需要一些 npm 中缺少的功能,并且有足够的磁盘空间

如果仍然很难在 npm 和 yarn 之间做出明确的决定,那就无需在意,随便用那一个都基本可以满足项目开发要求。

总结

包管理器对现代 web 开发非常的重要,本文比较了市场上两个最受欢迎的包管理器,它们都有各自的优点和缺点,选择最适合项目的。