来源: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 express@4.13.4
这将生成:
执行:
将产生:
你注意到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可能比其他方案具有明显的优势。
网友评论