自 node.js 出现至今,npm 做为包管理工具充斥着前端的工作,成为前端必备技能之一。
前端程序员已经习惯于使用 npm 来解决工作中遇到的各类问题,拓展以及丰富自己的代码。

一、关于 npm
npm 的优点是明显的:
可以加载应用所需代码,或将其整合
下载立即可用的独立工具包
限制代码的使用者
多版本管理
模块化的代码体验
活跃的社区以及技术交流
……
一时间,仿佛所有问题都可以用一行 npm install 解决。
然而,npm 自身的缺点也随着时间愈发明显。随着社区的壮大,项目依赖的增加,npm 也开始变得繁重。
因为归咎于复杂的依赖关系,当加载模块路径时就可能出现奇长无比的路径名,类似于 ./node_modules/package-A/node_modules/package-B/node-modules/some-file-name-in-package-c.js 这样的存在,而在 windows 下,260字节的文件名可能带来系统的异常。所以新的 npm为了解决类似的问题出现,采取了扁平化处理依赖的方法,但是这样的代价就是,npm 需要花费大量的时间构建一个完整的依赖树,问题解决了,耗时也增加了。
并且,复杂的版本控制,可能造成大家都在使用同一个包,但是出现了不同的效果,比如:package.json 里的 some-package: ^xx.xx.xxx,对于不同时期的 npm 来说,同一个文件所带来的效果可能是不同的,当然了,你也可以规定版本,单与此同时也对代码的灵活性以及实时更新造成了一定阻碍。
所以类似于 npm 的包管理工具便开始陆续出现,如 bower、component 和 volo等。今天我们就来说说 yarn。
二、什么是 yarn
yarn 是Google、Facebook、Exponent、Tilde 联合开发的一款包管理工具。
(这么看起来似乎也没什么了不起……)
可是当我们阅读 yarn 社区的第一篇文章时,会有如下的描述:
With Yarn, engineers still have access to the npm registry, but can install packages more quickly and manage dependencies consistently across machines or in secure offline environments. Yarn enables engineers to move faster and with confidence when using shared code so they can focus on what matters — building new products and features.
什么意思?更快、更有信心(更稳定)以及脱机,或者如官网首页的醒目大字所说:

这么看起来就很有趣了,尤其一个 more 几乎可以说就是把 npm 单拎出来点名批评了。一定程度上,我们可以说 yarn 其实就是针对 npm 的缺点而定制的一款包管理工具,在其缺点上都进行了优化。
在 github 上的 star 数量,yarn几乎达到了 npm 的两倍,可见开发者对于 yarn 的关注度非同一般。
不过也要注意一点,yarn 不托管包,没有自己的仓库,它只是在拉取的时候进行了优化与处理,包的来源依旧为 npm 或者其他你所指定的仓库。

三、yarn 的使用
在这里,我们只以 vue-cli3为例介绍简单的 yarn 使用方法,以便后续说明。
1、首先,你需要安装 yarn。
在 yarn 最初时期,是托管在 npm 上的,推荐的安装方式也是我们所熟知的
/* 废除 */npm install -g yarn
然而不论是 yarn 对于 npm 的稳健性的质疑
注意:通常情况下不建议通过npm进行安装。
npm安装是非确定性的,程序包没有签名,并且npm除了做了基本的SHA1哈希之外不执行任何完整性检查,这给安装系统程序带来了安全风险。
基于这些原因,强烈建议你通过最适合于你的操作系统的安装方法来安装yarn。
———— 摘自 yarn 官网
亦或是其他什么原因,现在的 yarn 推荐的安装方式是针对不同的系统,采用不同的安装方式。当然,前提是你已经安装有 node ^4.8.0 || ^5.7.0 || ^6.2.2 || >=8.0.0 环境。
我是 macOS,所以采用 brew install yarn。安装完成后输出版本号
localhost:~ dingyu$ yarn version
yarn version v1.12.3 // 成功!2、安装 vue-cli3 项目脚手架
执行yarn global add @vue/cli全局安装 vue-cli3
3、创建 vue 项目
在创建项目时,选择use YARN,脚手架会自动以 yarn 为包来源创建 vue 项目,而且 yarn 的界面非常有好(仅在 mac 下) 
4、运行服务
与 npm 类似地
cd hello-yarn
yarn serve这样一个基于 yarn 的 vue 项目就搭建成功了(撒花)
5、包的安装
yarn add lodash即可
四、yarn 有什么不同
1、快
同样创建一个项目,我们在使用 yarn 时可以明显感受到速度快于 npm 项目,如图yarn 创建项目界面所示,我们通常创建一个 vue 项目,并完成依赖包的下载,通常只需要花费 30s 左右的时间,这在 npm 项目中是无法想象的。
是什么造成了这种情况呢?
yarn 充分利用了缓存,加载过的包会被放进缓存内,当再次加载相同包的时候会优先读取缓存,并清除相对应的请求,这意味着,当我们手动删除 modules,断网,然后再次运行 yarn 的时候,这些包依然会完整的被加载进项目内。也就是说,即使没有网,只要我曾经创建过vue 项目并且没有清空 yarn 的缓存,我就依然可以继续线下创建项目。
yarn 另一个最大的特点就是,它多个包的下载与安装是并行进行的,这一点严重区别于 npm,同时也是 yarn 速度的关键。
2、稳
我们需要知道,package.json只能锁定大版本,而对于小版本无能为力。
当我们生成一个 yarn 项目的时候,对应会有一个 yarn.lock 文件生成。记得我们刚才说过由于版本号的区别造成的项目不可用么?yarn.lock 的作用就是:
锁定此项目中安装包的当前版本号(避免^xx.xx.xx)
锁定未注明的二级、三级...依赖中的小版本号
这使得在不同时间中,代码可以达到最大程度的一致。
相比较与 npm 需要手动增加npm-shrinkwrap.json,yarn.lock是默认生成,自动更新的,可见在 yarn 创始之初,稳定性就被重视。
当然,现在 npm5 中,也会默认生成package-lock.json,起作用与yarn.lock完全一致。
而 yarn.lock 还有顶级 lockfile 优先级最高最优先,完全被 yarn 管理等特性。
另外,当在 npm 中对于某一依赖包加载失败后,整个项目将会终止,然而在 yarn 中,若某一依赖加载失败,yarn 将会回弹,持续重试直至成功。
在上图中,我们可以看到,新的 npm5 中的package-lock.json与yarn.lock在视觉上是非常相似的。
3、安全
在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。而 npm 在安装时,就会执行包中所包含代码,带来安全隐患。
4、可迁移
受益于同格式的package.json,npm项目与yarn项目可以做到无缝转换,你所需要做的准备工作仅是熟悉yarn cli的命令行工具
| npm (v5) | Yarn |
|---|---|
npm install | yarn install |
| (N/A) | yarn install --flat |
| (N/A) | yarn install --har |
npm install --no-package-lock | yarn install --no-lockfile |
| (N/A) | yarn install --pure-lockfile |
npm install [package] | yarn add [package] |
npm install [package] --save-dev | yarn add [package] --dev |
| (N/A) | yarn add [package] --peer |
npm install [package] --save-optional | yarn add [package] --optional |
npm install [package] --save-exact | yarn add [package] --exact |
| (N/A) | yarn add [package] --tilde |
npm install [package] --global | yarn global add [package] |
npm update --global | yarn global upgrade |
npm rebuild | yarn add --force |
npm uninstall [package] | yarn remove [package] |
npm cache clean | yarn cache clean [package] |
rm -rf node_modules && npm install | yarn upgrade |
npm version major | yarn version --major |
npm version minor | yarn version --minor |
npm version patch | yarn version --patch |
五、yarn的使用
yarn如同npm一样,提供了专属的YARN CLI(参见:https://yarn.bootcss.com/docs/cli/)供快速开发了解。yarn 的使用,阅读yarn官方文档即可快速准确地使用。其中最主要的几条命令如下:
初始化一个新项目
yarn init
添加依赖包
yarn add [package]
yarn add [package]@[version]
yarn add [package]@[tag]
将依赖项添加到不同依赖项类别中
分别添加到 devDependencies、peerDependencies 和 optionalDependencies(参见:
https://yarnpkg.com/lang/zh-hans/docs/dependency-types/)类别中:
yarn add [package] --dev
yarn add [package] --peer
yarn add [package] --optional
升级依赖包
yarn upgrade [package]
yarn upgrade [package]@[version]
yarn upgrade [package]@[tag]
移除依赖包
yarn remove [package]
安装项目的全部依赖
yarn 或 yarn install
六、是否选择yarn
yarn 相对于 npm 的优势是明显的。
yarn在一些关键问题上有针对性的进行了解决,提高了整体的性能、稳定性以及安全性
yarn的维护团队专业水平高,更新稳定,维护迅速
主流框架、工具类等均对 yarn 进行了与 npm 同级别的支持,发展速度快
凭借这几点,了解yarn就是一个必备技能。
然而如果你习惯了npm的使用,尤其在npm5中已经包含了package-lock.json的前提下, 对原有项目进行维护,那么在项目的开发中,是否使用yarn就更多地取决于个人了。
并且,由于 yarn 提出的思路,npm 也开始在最新版本中有针对性的解决自己的问题,将来,二者一定会展开一场竞赛,孰优孰劣还需要等待开发者的验证。

