在單一儲存庫中執行任務
每個單一儲存庫都有兩個主要的建構區塊:工作區和任務。想像一下,你有一個包含三個工作區的單一儲存庫,每個工作區有三個任務
這裡,apps/web
和 apps/doc
都使用 packages/shared
中的程式碼。事實上,當它們建置(透過 build
)時,它們需要 packages/shared
首先建置。
大多數工具並未針對速度進行最佳化
想像一下,我們想要在所有工作區中執行所有任務。使用像 yarn
這樣的工具,你可以執行像這樣的指令碼
yarn workspaces run lint
yarn workspaces run test
yarn workspaces run build
這表示任務會像這樣執行
如你所見,lint
會在所有工作區中執行。然後,build
會執行 - 首先執行 shared
。最後,test
會執行。
這是執行這些任務最慢的方法。每個任務都需要等到前一個任務結束才能開始。為了改善這一點,我們需要一個可以多工的工具。
Turborepo 可以多工
Turborepo 可以透過了解任務之間的依賴關係,為我們的任務安排最大速度。
首先,我們在 turbo.json
中宣告我們的任務
{
"$schema": "https://turbo.dev.org.tw/schema.json",
"pipeline": {
"build": {
"outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**"],
// ^build means `build` must be run in dependencies
// before it can be run in this workspace
"dependsOn": ["^build"]
},
"test": {},
"lint": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
接下來,我們可以用這個取代我們的 yarn workspaces
腳本
- yarn workspaces run lint
- yarn workspaces run test
- yarn workspaces run build
+ turbo run lint test build
當我們執行它時,Turborepo 會在所有可用的 CPU 上多工執行儘可能多的任務,表示我們的任務會像這樣執行
由於 lint
和 test
在 turbo.json
中未指定 dependsOn
,因此會立即執行。
shared
內部的 build
任務會先完成,然後 web
和 docs
會在之後進行建置。
定義管線
pipeline
設定會宣告您的單一儲存庫中哪些任務彼此依賴。以下是一個範例
{
"$schema": "https://turbo.dev.org.tw/schema.json",
"pipeline": {
"build": {
// A workspace's `build` task depends on that workspace's
// topological dependencies' and devDependencies'
// `build` tasks being completed first. The `^` symbol
// indicates an upstream dependency.
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**"]
},
"deploy": {
// A workspace's `deploy` task depends on the `build`,
// `test`, and `lint` tasks of the same workspace
// being completed.
"dependsOn": ["build", "test", "lint"]
},
"test": {
// A workspace's `test` task depends on that workspace's
// own `build` task being completed first.
"dependsOn": ["build"],
// A workspace's `test` task should only be rerun when
// either a `.tsx` or `.ts` file has changed.
"inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
},
// A workspace's `lint` task has no dependencies and
// can be run whenever.
"lint": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
您可以在下一區段 任務相依性 中,進一步了解如何設定您的任務。
從根目錄執行任務
turbo
can run tasks that exist in the package.json
file at the root of the monorepo.
These must be explicitly added to the pipeline configuration using the key syntax "//#<task>"
. This is
true even for tasks that already have their own entry. For example, if your pipeline declares a "build"
task,
and you want to include the build
script defined in the monorepo's root package.json
file with
turbo run build
, you must opt the root into it by declaring "//#build": {...}
in your configuration.
Conversely, you do not need to define a generic "my-task": {...}
entry if all you need is "//#my-task": {...}
.
定義根目錄任務 format
,並將根目錄選入 test
的範例管線如下
{
"$schema": "https://turbo.dev.org.tw/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**"]
},
"test": {
"dependsOn": ["^build"],
},
// This will cause the "test" script to be included when
// "turbo run test" is run
"//#test": {
"dependsOn": [],
},
// This will cause the "format" script in the root package.json
// to be run when "turbo run format" is run. Since the general
// "format" task is not defined, only the root's "format" script
// will be run.
"//#format": {
"dependsOn": [],
"outputs": ["dist/**/*"],
"inputs": ["version.txt"]
}
}
}
關於遞迴的注意事項:定義在 monorepo 根目錄 package.json
中的腳本通常會呼叫 turbo
本身。例如,build
腳本可能是 turbo run build
。在這種情況下,在 turbo run build
中包含 //#build
將導致無限遞迴。正因如此,從 monorepo 根目錄執行的任務必須透過在管道設定中包含 //#<task>
來明確選擇加入。 turbo
包含一些盡力而為的檢查,以便在遞迴情況下產生錯誤,但由您決定只選擇那些本身不會觸發遞迴的 turbo
執行的任務。
逐步採用
在 turbo.json
中宣告任務後,您必須在 package.json
清單中實作它。您可以一次新增所有腳本,或一次新增一個工作區。Turborepo 會優雅地略過未在其各自的 package.json 清單中包含該任務的工作區。
例如,如果您的儲存庫有三個工作區(類似於上面提到的那些)
apps/
web/package.json
docs/package.json
packages/
shared/package.json
turbo.json
package.json
其中 turbo.json
宣告了一個 build
任務,但只有兩個 package.json
實作了那個 build
任務
{
"$schema": "https://turbo.dev.org.tw/schema.json",
"pipeline": {
"build": {
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
}
}
}
turbo run build
Turbo build 只會執行 build
指令碼給 web
和 docs
工作區。 shared
套件仍然會是任務圖表的一部分,但會優雅地略過。
Turborepo 的 Pipeline API 設計和此頁面文件是受到 Microsoft 的 Lage 專案(在新分頁中開啟) 的啟發。感謝 Kenneth Chau(在新分頁中開啟) 提出以如此簡潔優雅的方式展開任務的想法。