Yarn: Node.js的包管理器

来源:https://www.pluralsight.com/guides/yarn-a-package-manager-for-node-js

软件包管理器

Ruby有Bundler。

PHP有Composer。

Rust有Cargo。

Python有pip。

这些包管理器将安装和管理库依赖项过程自动化

在Node.js中,我们有npm作为默认的包管理器,它会在安装Node.js时自动包含。

Npm并不是完美的,有很多开源的替代品可以解决它的一些问题,比如ied、pnpm,以及最近的yarn。

一、介绍Yarn

Yarn于2016年10月由Facebook与Exponent、谷歌、Tilde合作发布。

Facebook Code上有一篇文章描述了构建这个新的包管理器的原因。

以下是一些亮点:

…当我们在内部进行扩展时,我们面临着在不同机器和用户之间安装依赖项时的一致性问题、拉入依赖项所需的时间,以及npm客户端自动执行某些依赖项代码的方式带来的一些安全问题。

我们还必须解决npm的shrinkwrap功能的问题,我们用它来锁定依赖版本。

…用npm更新单个依赖项也会根据语义版本规则更新许多不相关的依赖项。

使用Yarn的优点还不是大家都知道的。本指南将探索Yarn相对于npm的优势,并涵盖一些基本命令,帮助新用户适应定期使用Yarn。

这是Yarn的Github页面。这是一个很受欢迎的项目;在撰写本文时,它已经有21500个明星和500多个未决问题。Yarn与npm注册表兼容,拥有与npm相同的特性,但运行速度更快,更可靠。让我们一起来看看。

二、安装

你可以用npm安装yarn,但不推荐这样做:

npm install -g yarn

相反,如果您使用Windows,请下载安装程序(您需要安装Node.js)。

如果你使用的是iOS或Unix环境,最简单的方法是通过shell脚本:

curl -o- - L https://yarnpkg.com/install.sh|bash

在这个页面你可以找到更多的信息和其他的安装方法。

三、它是如何工作的

正如我们所知,Node.js依赖项被放置在项目的node_modules目录中。

这些依赖项是以不确定的方式安装的,这意味着目录结构和依赖项树依赖于安装依赖项的顺序。这种依赖关系是有问题的,因为它可能因机器而异。

为了解决这个问题,Yarn使用了一个lockfile (Yarn .lock)来确保每个文件都有相同的版本,从而导致node_modules目录在所有机器上的文件结构完全相同。

当依赖项被解析时,Yarn首先在本地(全局)缓存中查看包是否已经被下载。这一点,加上Yarn有效地排队和并行化请求的能力,使得Yarn比npm更快。

我们来测试一下。

四、NPM vs Yarn

这里的比较是用npm 4.05和Yarn 0.18.1进行的。

要用npm初始化一个项目,我们使用npm init:

npm init

Yarn有相同的init命令,但是问题和答案稍有不同:

Yarn init

要安装一个依赖并将其保存到package.json中,例如express(它有超过20个依赖项),我们在npm中执行:

npm install --save express

使用Yarn:

yarn add express

使用yarn的一个小好处是你可以少打字。只要你不使用npm i -S express这样的别名。

但是让我们来计算一下这些命令的执行时间。

Npm:

time npm install

Yarn:

time yarn add

从图片中可以看出,npm花了3.120秒,而Yarn花了2.588秒。

你还可以看到Yarn的输出更具有描述性,也更漂亮。不过,这些表情符号只能在Mac电脑上使用。

现在,让我们删除node_modules目录,并重复这个测试,看看Yarn的缓存是如何工作的:

yarn cache usage

这一次,Yarn的执行时间为1.455秒,比前一次提高了44%。比npm高出53%

当然,你可能会得到不同的结果,但是Yarn每次都会打败npm。

我们还可以看到生成了一个yarn.lock文件(为了方便起见,省略了一些部分)

注意Yarn使用的是https://registry.yarnpkg.com而不是https://registry.npmjs.org。

播客的NodeUp(约40:30马克)詹姆斯·凯尔(纱的主要开发者之一)说,现在,registry.yarnpkg.com是一个CNAME记录Cloudflare网络和实验目的,重定向到NPM注册表并添加一些性能特性。

现在将它与文件npm-shrinkwrap.json进行比较(它的目的与yarn.lock类似),当执行npm shrinkwrap时生成(为了简短,有些部分被省略了):

使用yarn的优点是自动生成yarn.lock;对于npm,你必须手动执行npm shrinkwrap。

有一点很重要,yarn.lock应该一直添加到源代码控制中。请记住,该文件确保依赖项的确定性安装。

现在,如果您指定了一个包的版本,您将注意到生成的package.json文件中有一个重要的区别。

例如,如果你执行:

npm install --save [email protected]

这将生成:

执行:

将产生:

你注意到Yarn的包里少了一个^吗?json文件吗?

很多人建议不要在我们的package.json文件中使用插入符号。

插入符号在安装时将依赖关系更新为最新的小版本。例如,如果有可用的2.4.1版本,即使^2.3.1是指定的,也会安装。在某些情况下,这可能会造成麻烦,因为有时即使在较小的版本中也会引入破坏性更改。

如果你想指定一个精确的版本,而不是使用npm的语义版本范围操作符(插入符号),你必须使用——save-exact(或它的别名-E),如:

然而,这是你必须知道并牢记在心的事情。另一方面,Yarn为您完成这种“插入符号处理”。如果这是您想要的东西,它取决于您的首选项和您正在使用的库

接下来,如果你已经有了一个package.json文件,你可以通过以下方式安装依赖:

yarn install

或者是:

yarn

如果你想删除一个依赖项,并更新package.json文件来反映它,你需要执行npm:

npm uninstall --save express

使用Yarn,你需要执行:

yarn remove express

这将默认更新你的package.json和yarn.lock文件。

yarn upgrade [package]命令将所有包(或单个命名包)升级到最新版本(某些规则适用),使用yarn upgrade package@version命令将已安装的包升级(或降级)到指定版本。在所有情况下,yarn.lock文件也将被重新创建。

接下来我将介绍npm和Yarn之间的一个关键区别。

五、npm dedupe

Yarn缺少的一个特性相当于npm dedupe,这是一个减少重复依赖的命令。由于一个项目可以有相同依赖关系的多个版本,因此重复数据删除命令可以派上用场。

在后台,npm重复数据删除会搜索依赖树,并试图通过将依赖项向上移动来简化整个目录结构(即使没有发现重复项),这样它们就可以被多个依赖包更有效地共享。如果一个合适的版本已经存在于目标位置,它将保持不变,但其他副本将被删除。这将导致扁平化和重复数据删除树。

另一方面,Yarn安装命令有一个——flat标志:

yarn install --flat

在第一次运行时,它会提示您为每个依赖树上有多个版本的包选择一个单独的版本。这些将添加到您的package.json决议字段下。但这与npm dedupe不同,后者通过删除来删除重复数据。

这个差异意味着Yarn生成的node_modules目录可以比npm生成的node_modules目录占用更多的磁盘空间。

然而,这种权衡可能不会对您、您的工作流或您的业务产生重大影响。

六、Yarn中的其他有用命令

本节将介绍您应该了解的其他Yarn命令。您可以在这里看到Yarn命令及其选项的完整列表。

首先,Yarn有一个许可证检查器。它会给你与每个包相关联的许可证(和源代码的URL):

 yarn licenses ls

除了ls之外,yarn许可证generate-discaimer将从您安装的所有包中输出所有许可证的内容。

要获取一个包的信息,使用yarn info:

yarn info cookie

您还可以询问您的packages.json文件中的一个或多个包的版本信息,如当前安装的版本、基于semver的期望版本和最新可用版本:

yarn outdated

最后,Yarn可以显示为什么一个包、包文件夹或包文件夹中的文件被安装:

yarn why xxx

结论

yarn已经在Facebook的生产中使用。此外,正如本指南中所展示的,它是npm的一个非常好的高性能替代方案。

对于简单的个人项目来说,也许你使用的方法并没有多大区别。然而,对于更大的项目(取决于您的需求),Yarn可能比其他方案具有明显的优势。

你可能感兴趣的:(Yarn: Node.js的包管理器)