Yarn 從 1.0 版開始支持 Workspace (工作區(qū))。
Workspace 能更好的統(tǒng)一管理有多個項目的倉庫矩肩,既可在每個項目下使用獨立的 package.json 管理依賴市殷,又可便利的享受一條 yarn 命令安裝或者升級所有依賴等遍搞。更重要的是可以使多個項目共享同一個 node_modules
目錄沥邻,提升開發(fā)效率和降低磁盤空間占用热某。
一句話總結(jié)就是可以大大簡化對多個項目的統(tǒng)一管理罩引。
很多知名的開源項目也使用了 Yarn Workspace嘹悼,如 vue嵌器、react肛真、jest 等。
1. Yarn Workspace 共享 node_modules
依賴詳解
回看下面的帶兩個子項目的經(jīng)典 Node.js 項目:
projects/
|--project1/
| |--package.json
| |--node_modules/
| | |--a/
|--project2
| |--package.json
| |--node_modules/
| | |--a/
| | |--project1/
project1/package.json:
{
"name": "project1",
"version": "1.0.0",
"dependencies": {
"a": "1.0.0"
}
}
project2/package.json:
{
"name": "project2",
"version": "1.0.0",
"dependencies": {
"a": "1.0.0",
"project1": "1.0.0"
}
}
沒有使用 Yarn Workspace 前爽航,需要分別在 project1
和 project2
目錄下分別執(zhí)行 yarn|npm install
來安裝依賴包到各自的 node_modules
目錄下蚓让∏溃或者使用 yarn|npm upgrade
來升級依賴的包。
這會產(chǎn)生很多不良的問題:
如果 project1 和 project2 有相同的依賴項目 a历极,a 都會各自下載一次窄瘟,這不僅耗時降低開發(fā)效率,還額外占用重復的磁盤空間趟卸;當 project 項目比較多的時候蹄葱,此類問題就會顯得十分嚴重。
-
如果 project2 依賴 project1锄列,而 project1 并沒有發(fā)布到 npm 倉庫图云,只是一個本地項目,有兩種方式配置依賴:
- 使用相對路徑(如 file: 協(xié)議)在 project2 中指定 project1 的依賴右蕊。
- 使用
yarn|npm link
來配置依賴琼稻。
第 1 種方式缺少版本號的具體指定,每次發(fā)布版本時都需要相應的依賴版本的修改饶囚;第 2 種方式需要自行手工操作帕翻,配置復雜易出錯。
需要 npm-2.0.0+ 才支持模塊間的相對路徑依賴萝风,詳見 npm 官方文檔 package.json/Local Paths
沒有一個統(tǒng)一的地方對全部項目進行統(tǒng)一構(gòu)建等嘀掸,需要到各個項目內(nèi)執(zhí)行
yarn|npm build
來構(gòu)架項目。
使用 Yarn Workspace 之后规惰,上述問題都能得到很好的解決睬塌。而且這是 Yarn 內(nèi)置的功能,并不需要安裝什么其他的包歇万,只需要簡單的在 projects 目錄(Yarn 稱之為 workspace-root)下增加如下內(nèi)容的 package.json 文件即可揩晴。
projects/package.json:
{
"private": true,
"workspaces": ["project1", "project2"] // 也可以使用通配符設置為 ["project*"]
}
開源社區(qū)則都基本上使用
"workspaces": ["packages/*"]
的目錄結(jié)構(gòu),這與 Lerna 的目錄結(jié)構(gòu)一致贪磺。
在 workspace-root 目錄下執(zhí)行 yarn install
:
$ cd projects
$ rm -r project1/node_modules
$ rm -r project2/node_modules
$ yarn install
yarn install v1.22.0
info No lockfile found.
[1/4] ?? Resolving packages...
[2/4] ?? Fetching packages...
[3/4] ?? Linking dependencies...
[4/4] ?? Building fresh packages...
success Saved lockfile.
? Done in 0.56s.
此時查看目錄結(jié)構(gòu)如下:
projects/
|--package.json
|--project1/
| |--package.json
|--project2
| |--package.json
|--node_modules/
| |--a/
| |--project1/ -> ./project1/
說明:
- projects 是各個子項目的上級目錄硫兰,術語上稱之為 workspace-root,而 project1 和 project2 術語上稱之為 workspace寒锚。
-
yarn install
命令既可以在 workspace-root 目錄下執(zhí)行劫映,也可以在任何一個 workspace 目錄下執(zhí)行,效果是一樣的刹前。 - 如果需要某個特殊的 workspace 不受 Yarn Workspace 管理泳赋,只需在此 workspace 目錄下添加
.yarnrc
文件,并添加如下內(nèi)容禁用即可:workspaces-experimental false
- 在 project1 和 project2 目錄下并沒有 node_modules 目錄(特殊情況下才會有喇喉,如當 project1 和 project2 依賴了不同版本的 a 時)祖今。
-
/node_modules/project1
是/project1
的軟鏈接,軟鏈接的名稱使用的是/project1/package.json#name
屬性的值拣技。 - 如果只是修改單個 workspace衅鹿,可以使用
--focus
參數(shù)來快速安裝相鄰的依賴配置從而避免全部安裝一次撒踪。
2. 可用的 Yarn Workspace 命令
2.1. yarn workspace <workspace_name> <command>
針對特定的 workspace 執(zhí)行指定的 <command>
,如:
$ yarn workspace project1 add vue --dev 《 往 project1 添加 vue 開發(fā)依賴
$ yarn workspace project1 remove vue 《 從 project1 移除 vue 依賴
在 {workspace}/package.json#scripts
中定義的腳本命令大渤,也可以作為 <command>
來執(zhí)行。
下面是一個利用這個特點創(chuàng)建統(tǒng)一構(gòu)建命令的例子:
projects/package.json:
{
"scripts": {
"build": "yarn workspaces run build"
}
}
project1|project2/package.json:
{
"scripts": {
"build": "rollup -i index.js -f esm -o dist/bundle.js"
}
}
執(zhí)行 yarn build
的結(jié)果:
$ yarn build
yarn run v1.22.0
$ yarn workspaces run build
> project1
$ rollup -i index.js -f esm -o dist/bundle.js
index.js → dist/bundle.js...
created dist/bundle.js in 70ms
> project2
$ rollup -i index.js -f esm -e project1 -o dist/bundle.js
index.js → dist/bundle.js...
created dist/bundle.js in 80ms
? Done in 2.45s.
2.2. yarn workspaces <command>
2.2.1. yarn workspaces run <command>
在每個 workspace 下執(zhí)行 <command>
掸绞。如:
yarn workspaces run test
將會執(zhí)行各個 workspace 的 test script泵三。
2.2.2. yarn workspaces info [--json]
顯示當前各 workspace 之間的依賴關系樹。
$ yarn workspaces info
yarn workspaces v1.21.1
{
"project1": {
"location": "project1",
"workspaceDependencies": [],
"mismatchedWorkspaceDependencies": []
},
"project2": {
"location": "project2",
"workspaceDependencies": [
"project1"
],
"mismatchedWorkspaceDependencies": []
}
}
? Done in 0.12s.
相關源代碼已放在 Github 上衔掸,詳見這里烫幕。