为什么你应该用Yarn而不是Npm来管理你的项目依赖?

1,750
因为Yarn有离线安装的功能,特别是在国内网络环境不大好的情况下,这个功能尤为有用。

问题

我们经常遇到的一种情况是:你设置好了你的网络,顺利地安装好了一切依赖,写好了package.jsonnpm给你自动生成了一个package-lock.json,在你的电脑上没有问题,但是你上传到git,再交给别的同学或者上传到服务器的时候,他们却怎么npm install也不成功了,这是因为为了确保一致性,npmpackage-lock.json里写明了每一个包的网络下载路径,而你同学的网络环境没有你这里好,所以你能成功下载的东西到他这里就下载不了了,结果为了这个网络设置又要折腾很长时间,虽然说国内也有淘宝镜象的cnpm这样的替代品,但也不时出现各种奇怪现象,还是不如正宗的npm顺畅。

Yarn

为了彻底解决这个问题,我们需要用到Yarn

Yarn的初始安装很简单:

brew install yarn

执行就更简单:

yarn

这时它会生成一个yarn.lock的文件,这个文件的内容和npm生成的package-lock.json文件很像,也包含了各个依赖包的网络下载路径(实际上,npmpackage-lock.json这个概念就是从yarn借鉴过来的)。然后你可以执行yarn start来启动开发环境,或者yarn run build来执行编译,npm能执行什么命令,yarn也可以。至此为止,似乎没有看到yarn有什么神奇之处。

离线

下面我们开始为yarn设置离线安装环境,这才是yarn最精彩的地方。

为了能有一个地方存储yarn下载下来的安装包,我们需要设置一个与项目和机器彻底无关的文件夹,假定我们就在电脑的根目录下存储这些文件,我们首先建立一个文件夹,允许别人访问它:

sudo mkdir /Projects
sudo chmod 777 /Projects

然后,我们告诉yarn到这里来存储和读取离线安装包:

yarn config set yarn-offline-mirror /Projects/yarn-offline-mirror

这时候,yarn会在你当前用户的根目录下生成一个.yarnrc的文件,你可以把这个文件搬到你项目的根目录下:

mv ~/.yarnrc ./

这个文件的内容很短,打开来看一下:

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


lastUpdateCheck 1520049128107
yarn-offline-mirror "/Projects/yarn-offline-mirror"

它的大意是说这是一个自动生成的文件,你不应该直接修改文件内容(不过其实如果你知道你在干的是什么的,修改也是没有关系的,毕竟不是二进制文件)。这里面就列出了我们离线包的存储位置。

接下来我们开始往我们的离线文件夹灌入内容。我们先把我们当前项目的node_modules文件夹和yarn.lock文件删除:

rm -rf node_modules/ yarn.lock

然后,我们执行一下

yarn install

这时候你会看到yarn不但重新生成了node_modules文件夹和yarn.lock文件,并且把下载下来的安装包全都放入了我们刚才设定好的离线安装路径/Projects/yarn-offline-mirror

验证

我们怎么验证yarn确实可以离线安装呢?我们还是先把node_modules文件夹删掉,注意,这次不要再删yarn.lock文件了:

rm -rf node_modules

为了彻底起见,我们把yarn的缓存也删掉:

yarn cache clean

然后,我们把wifi关掉,把网线拔掉,然后我们再执行:

yarn install -offline

成功了!在没有任何网络的情况下,我们继续可以重建node_modules文件夹,它取的就是我们刚才设定好的/Projects/yarn-offline-mirror里的内容。

意义

那么这有什么意义呢?仅仅如此还是不够的,我们需要把整个yarn-offline-mirror上传到我们自己的git库里,为它单独建一个库,这样我们的多个项目就可以共享这同一个yarn-offline-mirror,而不必浪费太多的空间。并且由于这是在我们自己的文件系统中,如果是在服务器端或者其他同事的电脑中执行yarn install -offline的话,它也不会再去访问npm的官方网站获取安装包,毕竟那样访问不通的概率很大,在中国目前这种网络环境下。

这么麻烦,为什么我不直接把整个node_modules文件夹放入git库呢?这不也是一样的效果吗?某种意义上说,的确是这样的,但是node_modules里存储的是解压缩之后的所有文件,动辄几万甚至几十万个文件都很常见,所以通常我们在建项目的时候是把node_modules文件夹放在.gitignore文件中忽略掉的。而yarn-offline-mirror里存放的是安装包本身,是未经解压缩的.tgz文件,一般一个项目几十最多几百个文件就够了,这样对于我们的git服务器的管理也是一件好事,所以我们可以把它放在git里管理起来。

参考

你可以更进一步了解一下官方介绍,如果你感兴趣的话。

最后,希望你能用的开心快乐!