用 Yarn 代替 npm 管理你的 node 依赖项

为什么放弃 npm

作为 node 自带的依赖管理工具 npm,简单并且好用或者说够用。或许因为是官方的原因吧,曾经我也没想过我最终会放弃这货。但是不得不说体验了一把 yarn,就已经回不去了。
为什么?原因很直接:npm 的速度实在实在太慢了。它或许没有什么太大的功能缺陷,但是真的,它太慢了。仅仅因为这个,和 yarn 一对比,几乎没有多少人能回去。因为 yarn 不仅飞快、扩展了功能,而且还保证了对 npm 的兼容。

用事实说话

我博客项目的前端依赖有一千个以上(算上不同的父级依赖间接相同的子依赖):

用 npm 安装,花了整整一分钟。换做 yarn 只用了不到10秒。来来回回我测试了几次,排除了任何一个有网络问题的情形。凭这点,我就有一万个重复的理由换上 yarn。

安装 yarn

yarn 虽然是一个 NodeJs 程序,但并不建议通过 npm 安装(虽然 npm 仓库有 yarn)。好消息是官方给 Linux 提供了源。如果是 DEB 系列的系统,可以运行下面三条命令,分别是添加公钥、写入源列表、更新仓库和安装 yarn:

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb http://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn

其他系统请详情参考官方安装文档

npm 对应的 yarn 命令

npm 是一个 CLI 程序,yarn 自然也是。npm 的常用命令 yarn 都有与之对应的命令,并且保证兼容(配置文件)。

  1. 添加/安装 一个新的依赖,对应 npm install [package_name] –save

    yarn add [package_name]
    

    和 npm 的不同是 yarn 会默认更新 package.json 文件,添加好依赖项。而 npm 需要 –save 参数。
    如果需要添加到指定环境的依赖,例如 npm install [package_name] –save-dev,yarn 仅需这样:

    yarn add [package_name] --dev
    
  2. 安装所有依赖,对应 npm i 或者 npm install

    yarn
    

    yarn 命令不加参数会默认当作 yarn install,所以二者相同。

  3. 运行命令,对应 npm run [command]

    yarn run [command]
    

    和 npm 相同。读取 package.json 里边的 scripts 配置。

  4. 初始化一个 node 项目,对应 npm init

    yarn init
    

    和 npm 相同。以交互形式创建 package.json 文件。

  5. 更新依赖

    yarn upgrade
    

    npm 没有与之对应的功能。如果想更新,需要删除 node_modules 文件夹 重新执行一遍卡顿的 npm install

yarn.lock

当使用过 yarn 之后,会生成一个 npm 没有的文件,也就是 yarn.lock 文件。
如果熟悉 ruby 和 rust 等语言的包管理的童鞋瞬间就能明白它是干嘛的了,因为这个东西并不是独创,而是很多包管理都采用的一种机制。它的目的是固定依赖版本。
因为 yarn 或者 npm 安装的依赖默认是取一个范围,而不是指定死的某个版本。当然这种机制在开发者遵循版本规范的前提下肯定是优于指定版本的。但是,一个项目在开发过程中,依赖版本就不应该变更了。而 package.json 一直是一个范围版本,所以可能在不同的时间不同的设备上安装出不同版本的依赖,这绝对是不利于团队或者分布式开发的。
所以 yarn.lock 的意图就是将初次由 yarn 安装的依赖选择的版本记录下来。当之后有第二个人安装的时候就不会继续从范围选择而是直接拉取记录好的版本,以达到每个人的版本都一定是一致的效果。所以,你应该明白了,这个文件是一定要加入版本控制系统的,不然就失去了意义。

yarn.lock 内容截取:

aws-sign2@~0.6.0:
  version "0.6.0"
  resolved "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"

aws4@^1.2.1:
  version "1.5.0"
  resolved "http://registry.npm.taobao.org/aws4/download/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755"

上面的记录的意思,一般就是 某个版本范围(xx 版本以上),拉取的具体版本,拉取地址等。

Yarn 速度快的秘密

具体的细节原因说不上来,目前未对 yarn 有过多研究。但是从官网的描述来看主要是两点:

  1. 优秀的缓存机制(有 lock 对应版本直接取缓存,npm 没有 lock,每次都要验证版本烦不烦啊… 活该你慢)
  2. 并行安装依赖项(npm 居然不能并行安装多个依赖… 好吧 难怪你慢)

最后提一件事

我安装 yarn 的时候… 居然发现命令行不对劲。虽然 yarn 已经是全局程序了,但是貌似执行的并不是 node 的那个 yarn,而是某个 Java 相关的程序。把我吓了一跳。
后来经过我的深思熟虑… 妈的 Hadoop 也有一个 YARN 啊,我把这货也加到环境变量了~~ 改名,OK。

总结

换上 yarn,成本低(零迁移),速度快,更方便的 CLI 。何乐而不为?干嘛还要忍受 npm 的摧残?为了那安装依赖的时候顺便喝杯咖啡的“人性化”吗?