使用Yarn Workspace管理多project repo
node的包管理方式和js社区重复造轮子的坏习惯一直为人所诟病。Yarn的横空出世很好的解决了单个package.json之下依赖重复的问题。对于多个package.json的项目,有没有办法解决呢?答案是Yes,Yarn workspace能很好的帮你做到这一点。
背景
管理过在一个 javascript repo 下面有多个子 project 的同学可能都遇到过依赖管理困难的问题。对于一些公用的包(比如 node-sass),我们想尽可能保证版本的一致,享受 yarn 的 hoist 特性,同时也不想下载多次。但是对于一些特殊的包,我们又想保持各个 repo 的独立性。 在 Yarn 1.0 版本以前,以上念想其实是很去实现的,我们不得不花费大量的人力去维护我们各个子 project 的依赖包关系。但是 Yarn 在 1.0 版本引入了workspace这个特性之后,这些问题就不再存在了。
什么是 workspace
yarn 官方对于 workspace 的定义是It allows you to setup multiple packages in such a way that you only need to run yarn install once to install all of them in a single pass.
。简而言之,workspace 能帮助你更好的管理有多个子 project 的 repo。你既可以在每个子 project 下使用独立的 package.json 管理你的依赖,又可以享受一条 yarn 命令安装或者升级所有依赖的都便利性。
workspace 能帮你做什么
简而言之,workspace 能帮你做这么两件事情
简化你的工作流
当你有多个子 project 的时候,你可能做的最多的事情就是分别进入每个文件夹,然后执行yarn install
或者 yarn upgrade foo
。
但是引入 workspace 之后你需要的只是一条在根目录运行yarn install
或者yarn upgrade foo
命令,你的所有的依赖都会被安装或者更新。
降低包安装和包升级的成本
这里讲的成本主要指的是时间成本和管理的精力成本。
时间成本
在使用 workspace 之前,你想要安装整个 repo 的依赖时,你需要独立安装每个子 project 的依赖。这就意味着,如果你的 repo 下面同时以来于 node-sass,你需要重复下载三次 node-sass 的安装包。当你的子 project 或者包依赖并不是特别多的时候,这些时间成本似乎影响并不是那么大。但是随着你的 repo 越来越大,依赖越来越复杂,消耗的时间也会变得越来越恐怖。 在引入 workspace 之后,yarn 会帮助你分析各个子 project 里面的依赖关系,保证所有子 project 里面共同的依赖只会被下载和安装一次,大大缩减安装的时间。
精力成本
设想我们引用了一个有严重安全漏洞的包 foo,我们想要将整个 repo 中的这个包都升级到最新版本来修复这个严重的安全漏洞。在没有使用 workspace 之前,你需要仔细且耐心的遍历每个子 project 的 package.json 文件,然后手动执行升级操作。
在引入 workspace 之后,你大可以在 repo 的根目录简单运行一条yarn upgrade foo
命令,你的所有子 project 中依赖的 foo 包都会自动升级到 package.json 里面指定的版本。
当然,如果你想单独的升级某个子 project 的包,可以简单的使用yarn workspace <workspace-name> upgrade …
来做到。
怎么使用 workspace
yarn workspace 并不需要安装什么其他的包,只需要简单的更改 package.json 便可以工作。 首先我们需要确定workspace root,一般来说 workspace root 都会是 repo 的根目录。
package.json
{
"private": true,
"workspaces": ["workspace-a", "workspace-b"]
}
首先需要注意的是,repo 根目录下的 private 必须设置成 true,否则 workspace 不会被起用。 在 package.json 中我们新加入了 workspaces 这个属性,其值是一个字符串数组,每一个字符串指代了一个 workspace 的路径,这些路径支持 glob 匹配。需要注意的是,这里的路径指向指的是 package.json 所在文件夹文件夹名。而对于各个子 project,我们并不需要做其他的配置。
接下来,我们开始申明依赖
workspace-a/package.json
{
"name": "workspace-a",
"version": "1.0.0",
"dependencies": {
"cross-env": "5.0.5"
}
}
workspace-b/package.json
{
"name": "workspace-b",
"version": "1.0.0",
"dependencies": {
"cross-env": "5.0.5",
"workspace-a": "1.0.0"
}
}
接下来在根目录执行 yarn install
{{