Turborepo logo

設定任務

Turborepo 將始終按照您的 turbo.json 設定套件圖中描述的順序執行任務,並在可能的情況下將工作平行化,以確保一切盡可能快速地執行。這比一次執行一個任務更快,也是 Turborepo 如此快速的部分原因。

例如,yarn workspaces run lint && yarn workspaces run test && yarn workspaces run build 看起來會像這樣

A graphical representation of `turbo run lint test build`. It shows all tasks running in parallel, with much less empty space where scripts are not being ran.

但是,為了使用 Turborepo 更快地完成相同的工作,您可以使用 turbo run lint test build

A graphical representation of `turbo run lint test build`. It shows all tasks running in parallel, with much less empty space where scripts are not being ran.

開始使用

根目錄 turbo.json 檔案是您註冊 Turborepo 將執行的任務的地方。一旦您定義了任務,您就可以使用 turbo run 執行一個或多個任務。

  • 如果您是從頭開始,我們建議使用 create-turbo 建立新的儲存庫,並編輯 turbo.json 檔案以試用本指南中的程式碼片段。
  • 如果您要在現有的儲存庫中採用 Turborepo,請在儲存庫的根目錄中建立 turbo.json 檔案。您將使用它來了解本指南中其餘的設定選項。
turbo.json
package.json

定義任務

tasks 物件中的每個鍵都是可以由 turbo run 執行的任務。Turborepo 將在您的套件中搜尋 package.json 中與任務名稱相同的腳本

若要定義任務,請使用 turbo.json 中的 tasks 物件。例如,一個沒有相依性和沒有輸出的基本任務,名為 build,可能看起來像這樣

./turbo.json
{
  "tasks": {
    "build": {} // Incorrect!
  }
}

如果您在此時執行 turbo run build,Turborepo 將平行執行您套件中的所有 build 腳本,並且不會快取任何檔案輸出。這將很快導致錯誤。 您缺少一些重要的部分,才能使其按您的預期工作。

以正確的順序執行任務

dependsOn用於指定在另一個任務開始執行之前必須完成的任務。例如,在大多數情況下,您希望您的函式庫的 build 腳本在您的應用程式的 build 腳本執行之前完成。若要執行此操作,您可以使用以下 turbo.json

./turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"] 
    }
  }
}

您現在擁有您期望的建置順序,先建置相依性,然後再建置相依者

但請小心。 此時,您尚未標記建置輸出以進行快取。若要執行此操作,請跳至 指定輸出 章節。

相依於具有 ^ 的相依性中的任務

^ 微語法告訴 Turborepo 從相依性圖的底部開始執行任務。如果您的應用程式相依於名為 ui 的函式庫,且該函式庫具有 build 任務,則 ui 中的 build 腳本將首先執行。成功完成後,您的應用程式中的 build 任務將執行。

這是一個重要的模式,因為它可以確保您的應用程式的 build 任務將擁有編譯所需的所有必要相依性。當您的相依性圖成長為具有多個層級的任務相依性的更複雜結構時,此概念也適用。

相依於同一套件中的任務

有時,您可能需要確保同一個套件中的兩個任務以特定的順序執行。例如,您可能需要在您的函式庫中執行 build 任務,然後再在同一個函式庫中執行 test 任務。若要執行此操作,請在 dependsOn 鍵中將腳本指定為純字串(不含 ^)。

./turbo.json
{
  "tasks": {
    "test": {
      "dependsOn": ["build"] 
    }
  }
}

相依於特定套件中的特定任務

您也可以指定要相依的特定套件中的個別任務。在下面的範例中,utils 中的 build 任務必須在任何 lint 任務之前執行。

./turbo.json
{
  "tasks": {
    "lint": {
      "dependsOn": ["utils#build"] 
    }
  }
}

您也可以更具體地說明相依任務,將其限制在特定的套件中

./turbo.json
{
  "tasks": {
    "web#lint": {
      "dependsOn": ["utils#build"] 
    }
  }
}

透過此設定,您的 web 套件中的 lint 任務只能在 utils 套件中的 build 任務完成後執行。

無相依性

某些任務可能沒有任何相依性。例如,用於在 Markdown 檔案中尋找錯字的任务可能不需要關心您的其他任務的狀態。在這種情況下,您可以省略 dependsOn 鍵或提供空陣列。

./turbo.json
{
  "tasks": {
    "spell-check": {
      "dependsOn": [] 
    }
  }
}

指定 outputs

Turborepo 快取您任務的輸出,以便您永遠不會重複執行相同的工作。我們將在 快取指南 中深入討論此問題,但讓我們首先確保您的任務已正確設定。

outputs 鍵告訴 Turborepo 檔案和目錄,當任務成功完成時,它應該快取這些檔案和目錄。如果未定義此鍵,Turborepo 將不會快取任何檔案。在後續執行中點擊快取將不會還原任何檔案輸出。

以下是一些常見工具的輸出範例

./turbo.json
{
  "tasks": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"] 
    }
  }
}

Glob 相對於套件,因此 dist/** 將處理每個套件輸出的 dist。如需更多關於為 outputs 鍵建立 globbing 模式的資訊,請參閱 globbing 規格

指定 inputs

inputs 鍵用於指定您要包含在任務雜湊中的檔案,以進行 快取。預設情況下,Turborepo 將包含套件中由 Git 追蹤的所有檔案。但是,您可以使用 inputs 鍵更具體地說明要包含在雜湊中的檔案。

例如,一個用於在 Markdown 檔案中尋找錯字的任务可以定義如下

./turbo.json
{
  "tasks": {
    "spell-check": {
      "inputs": ["**/*.md", "**/*.mdx"] 
    }
  }
}

現在,只有 Markdown 檔案中的變更才會導致 spell-check 任務錯過快取。

此功能選擇退出 Turborepo 的所有預設 inputs 行為,包括追蹤原始碼控制所追蹤的變更。這表示您的 .gitignore 檔案將不再受到尊重,您需要確保您不會使用 glob 擷取這些檔案。

若要還原預設行為,請使用 $TURBO_DEFAULT$ 微語法

使用 $TURBO_DEFAULT$ 還原預設值

預設的 inputs 行為 通常是您希望任務使用的行為。但是,您可以透過微調 inputs 以忽略已知不會影響任務輸出的檔案的變更,來提高某些任務的快取命中率。

因此,您可以使用 $TURBO_DEFAULT$ 微語法來微調預設的 inputs 行為

./turbo.json
{
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", "!README.md"] 
    }
  }
}

在此任務定義中,Turborepo 將對 build 任務使用預設的 inputs 行為,但將忽略對 README.md 檔案的變更。如果 README.md 檔案已變更,則任務仍會命中快取。

註冊根任務

您也可以使用 turbo 在 Workspace 根目錄中的 package.json 中執行腳本。例如,除了每個套件中的 lint 任務之外,您可能還想為 Workspace 根目錄中的檔案執行 lint:root 任務

./turbo.json
{
  "tasks": {
    "lint": {
      "dependsOn": ["^lint"]
    },
    "//#lint:root": {} 
  }
}

現在已註冊根任務,turbo run lint:root 現在將執行該任務。您也可以執行 turbo run lint lint:root 來執行您的所有 linting 任務。

何時使用根任務

  • Workspace 根目錄的 Linting 和格式化:您的 Workspace 根目錄中可能有程式碼,您想要進行 lint 和格式化。例如,您可能想要在根目錄中執行 ESLint 或 Prettier。
  • 增量移轉:當您移轉到 Turborepo 時,您可能會有一個中間步驟,其中有一些您尚未移動到套件的腳本。在這種情況下,您可以建立根任務以開始移轉,並稍後將任務分散到套件中。
  • 沒有套件範圍的腳本:您可能有一些在特定套件的上下文中沒有意義的腳本。這些腳本可以註冊為根任務,以便您仍然可以使用 turbo 執行它們,以達到快取、平行化和工作流程的目的。

進階使用案例

使用套件設定

套件設定 是直接放置在套件中的 turbo.json 檔案。這允許套件為其自己的任務定義特定行為,而不會影響儲存庫的其餘部分。

在具有許多團隊的大型 monorepo 中,這允許團隊更好地控制自己的任務。若要了解更多資訊,請造訪 套件設定文件

執行副作用

某些任務應始終執行,無論如何,例如快取建置後的部署腳本。對於這些任務,請在您的任務定義中新增 "cache": false

./turbo.json
{
  "tasks": {
    "deploy": {
      "dependsOn": ["^build"],
      "cache": false
    },
    "build": {
      "outputs": ["dist/**"]
    }
  }
}

可以平行執行的相依任務

某些任務可以平行執行,即使它們相依於其他套件。符合此描述的任務範例是 linters,因為 linter 不需要等待相依性中的輸出成功執行即可執行。

因此,您可能會想要像這樣定義您的 check-types 任務

./turbo.json
{
  "tasks": {
    "check-types": {} // Incorrect!
  }
}

這會平行執行您的任務 - 但不會考慮相依性中的原始碼變更。這表示您可以

  1. 對您的 ui 套件的介面進行重大變更。
  2. 執行 turbo check-types,在相依於 ui 的應用程式套件中命中快取。

這是錯誤的,因為應用程式套件將顯示成功的快取命中,儘管它尚未更新以使用新的介面。在您的編輯器中手動檢查應用程式套件中的 TypeScript 錯誤可能會顯示錯誤。

因此,您可以對您的 check-types 任務定義進行小幅變更

./turbo.json
{
  "tasks": {
    "check-types": {
      "dependsOn": ["^check-types"] // This works...but could be faster!
    }
  }
}

如果您再次測試在您的 ui 套件中進行重大變更,您會注意到快取行為現在是正確的。但是,任務不再平行執行。

為了滿足這兩個要求(正確性和平行性),您可以將 Transit Nodes 引入您的任務圖

./turbo.json
{
  "tasks": {
    "transit": {
      "dependsOn": ["^transit"]
    },
    "check-types": {
      "dependsOn": ["transit"]
    }
  }
}

這些 Transit Nodes 使用與任何 package.json 中的腳本都不符的任務,在您的套件相依性之間建立關係,因為它不執行任何操作。因此,您的任務可以平行執行 了解其內部相依性的變更。

在本範例中,我們使用了名稱 transit - 但您可以將任務命名為 Workspace 中尚未存在的任何腳本。

下一步

設定 turbo.json 文件中提供了更多選項,您將在接下來的指南中探索這些選項。現在,您可以開始執行一些任務,以了解基本原理是如何運作的。