
turborepo
熱門Turborepo monorepo 建置系統指南。觸發條件:turbo.json、任務流程管道(task pipelines)、dependsOn、快取(caching)、遠端快取(remote cache)、"turbo" CLI、--filter、--affected、CI 最佳化、環境變數、內部套件(internal packages)、monorepo 架構/最佳實踐以及邊界限制(boundaries)。 當使用者符合以下情境時使用:設定任務/工作流程/流程管道、建立套件、建置 monorepo、在應用程式之間共用程式碼、執行已變更/受影響的套件、除錯快取問題,或專案中含有 apps/packages 目錄。
Turborepo monorepo 建置系統指南。觸發條件:turbo.json、任務流程管道(task pipelines)、dependsOn、快取(caching)、遠端快取(remote cache)、"turbo" CLI、--filter、--affected、CI 最佳化、環境變數、內部套件(internal packages)、monorepo 架構/最佳實踐以及邊界限制(boundaries)。 當使用者符合以下情境時使用:設定任務/工作流程/流程管道、建立套件、建置 monorepo、在應用程式之間共用程式碼、執行已變更/受影響的套件、除錯快取問題,或專案中含有 apps/packages 目錄。
Turborepo Skill
適用於 JavaScript/TypeScript monorepo 的建置系統。Turborepo 會快取任務輸出,並根據相依性圖表(dependency graph)平行執行任務。
重要:優先使用 Package Tasks,而非 Root Tasks
請優先使用套件任務(Package tasks),而非根目錄任務(Root Tasks)。
建立任務/腳本/流程管道時,您必須預設使用套件任務:
- 將腳本新增至各個相關套件的
package.json - 在根目錄的
turbo.json中註冊該任務 - 根目錄的
package.json僅透過turbo run <task>委派執行
切勿在根目錄的 package.json 中編寫可以放在套件內的任務邏輯。這會破壞 Turborepo 的平行處理能力。
// 建議作法:將腳本放在各套件中
// apps/web/package.json
{ "scripts": { "build": "next build", "lint": "eslint .", "test": "vitest" } }
// apps/api/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
// packages/ui/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
// turbo.json - 註冊任務
{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"lint": {},
"test": { "dependsOn": ["build"] }
}
}
// 根目錄 package.json - 僅進行委派,無任務邏輯
{
"scripts": {
"build": "turbo run build",
"lint": "turbo run lint",
"test": "turbo run test"
}
}
// 請勿這樣做 - 會破壞平行處理能力
// 根目錄 package.json
{
"scripts": {
"build": "cd apps/web && next build && cd ../api && tsc",
"lint": "eslint apps/ packages/",
"test": "vitest"
}
}
根目錄任務(//#taskname)僅適用於確實無法存在於套件中的任務,例如 Vitest Projects 的 //#test、全域釋出腳本(release scripts),或是本身不會呼叫 turbo 的工具鏈。
次要規則:turbo run vs turbo
在程式碼或設定檔中撰寫指令時,請一律使用 turbo run:
// package.json - 一律使用 "turbo run"
{
"scripts": {
"build": "turbo run build"
}
}
# CI 工作流程 - 一律使用 "turbo run"
- run: turbo run build --affected
簡寫格式 turbo <tasks> 僅適用於由人類或 Agent 在終端機直接輸入的一次性指令。切勿將 turbo build 寫入 package.json、CI 或腳本中。
快速決策樹
「我需要設定任務」
設定任務?
├─ 定義任務相依性 → references/configuration/tasks.md
├─ Lint/型別檢查 (平行處理 + 快取) → 使用 Transit Nodes 模式 (見下方)
├─ 指定建置輸出 → references/configuration/tasks.md#outputs
├─ 處理環境變數 → references/environment/RULE.md
├─ 設定開發/監控任務 → references/configuration/tasks.md#persistent
├─ 特定套件設定 → references/configuration/RULE.md#package-configurations
└─ 全域設定 (cacheDir, daemon) → references/configuration/global-options.md
「我的快取沒有生效」
快取問題?
├─ 任務已執行但未還原輸出 → 缺少 `outputs` 鍵值
├─ 意料之外的快取未命中 (Cache miss) → references/caching/gotchas.md
├─ 需要除錯雜湊輸入值 (Hash inputs) → 使用 --summarize 或 --dry
├─ 想要完全跳過快取 → 使用 --force 或 cache: false
├─ 遠端快取 (Remote cache) 未生效 → references/caching/remote-cache.md
└─ 環境變數導致未命中 → references/environment/gotchas.md
「我只想執行有變更的套件」
只執行變更部分?
├─ 變更的套件 + 相依於它的套件 (推薦) → turbo run build --affected
├─ 自訂基準分支 → --affected --affected-base=origin/develop
├─ 手動 Git 比對 → --filter=...[origin/main]
└─ 檢視所有篩選選項 → references/filtering/RULE.md
--affected 是只執行已變更套件的主要方式。 它會自動與預設分支比對,並包含受影響的相依套件。
「我想要篩選套件」
篩選套件?
├─ 僅變更的套件 → --affected (見上方)
├─ 依套件名稱 → --filter=web
├─ 依目錄 → --filter=./apps/*
├─ 套件 + 前置相依套件 → --filter=web...
├─ 套件 + 後續受影響套件 → --filter=...web
└─ 複雜組合 → references/filtering/patterns.md
「環境變數無法正常運作」
環境變數問題?
├─ 變更在執行階段 (Runtime) 無法讀取 → 嚴格模式篩選 (預設)
├─ 快取命中但帶有錯誤環境變數 → 變數未列於 `env` 鍵值中
├─ .env 變更未引發重新建置 → .env 未列於 `inputs`
├─ 缺少 CI 環境變數 → references/environment/gotchas.md
└─ 框架專用變數 (NEXT_PUBLIC_*) → 透過推斷自動包含
「我需要設定 CI」
CI 設定?
├─ GitHub Actions → references/ci/github-actions.md
├─ Vercel 部署 → references/ci/vercel.md
├─ CI 中的遠端快取 → references/caching/remote-cache.md
├─ 僅建置有變更的套件 → --affected 旗標
├─ 跳過不必要的建置 → turbo-ignore (references/cli/commands.md)
└─ 無變更時跳過容器設定 → turbo-ignore
「我想在開發時監控檔案變更」
監控模式 (Watch mode)?
├─ 變更時重新執行任務 → turbo watch (references/watch/RULE.md)
├─ 帶有相依關係的開發伺服器 → 使用 `with` 鍵值 (references/configuration/tasks.md#with)
├─ 相依套件變更時重啟開發伺服器 → 使用 `interruptible: true`
└─ 持續執行的開發任務 → 使用 `persistent: true`
「我需要建立/組織套件結構」
套件建立/架構?
├─ 建立內部套件 → references/best-practices/packages.md
├─ 儲存庫結構 → references/best-practices/structure.md
├─ 相依性管理 → references/best-practices/dependencies.md
├─ 最佳實踐總覽 → references/best-practices/RULE.md
├─ JIT 與預先編譯 (Compiled) 套件 → references/best-practices/packages.md#compilation-strategies
└─ 在應用程式之間共用程式碼 → references/best-practices/RULE.md#package-types
「我應該如何組織 Monorepo 架構?」
Monorepo 架構?
├─ 標準配置 (apps/, packages/) → references/best-practices/RULE.md
├─ 套件類型 (apps vs libraries) → references/best-practices/RULE.md#package-types
├─ 建立內部套件 → references/best-practices/packages.md
├─ TypeScript 設定 → references/best-practices/structure.md#typescript-configuration
├─ ESLint 設定 → references/best-practices/structure.md#eslint-configuration
├─ 相依性管理 → references/best-practices/dependencies.md
└─ 強制執行套件邊界 → references/boundaries/RULE.md
「我想強制執行架構邊界」
強制執行邊界?
├─ 檢查違反規則項 → turbo boundaries
├─ 為套件打上標籤 → references/boundaries/RULE.md#tags
├─ 限制套件之間的匯入關係 → references/boundaries/RULE.md#rule-types
└─ 防止跨套件檔案直接匯入 → references/boundaries/RULE.md
關鍵反模式 (Critical Anti-Patterns)
在程式碼中使用 turbo 簡寫
建議在 package.json 腳本與 CI 流程管道中使用 turbo run。 簡寫格式 turbo <task> 主要設計給互動式終端機手動使用。
// 錯誤 - 在 package.json 中使用簡寫
{
"scripts": {
"build": "turbo build",
"dev": "turbo dev"
}
}
// 正確
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
# 錯誤 - 在 CI 中使用簡寫
- run: turbo build --affected
# 正確
- run: turbo run build --affected
根目錄腳本繞過 Turbo
根目錄 package.json 中的腳本必須委派給 turbo run,而不是直接執行任務。
// 錯誤 - 完全繞過 turbo
{
"scripts": {
"build": "bun build",
"dev": "bun dev"
}
}
// 正確 - 委派給 turbo
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
使用 && 串接 Turbo 任務
不要使用 && 串接 turbo 任務,讓 turbo 負責排程協調。
// 錯誤 - turbo 任務未使用 turbo run
{
"scripts": {
"changeset:publish": "bun build && changeset publish"
}
}
// 正確
{
"scripts": {
"changeset:publish": "turbo run build && changeset publish"
}
}
手動建置相依套件的 prebuild 腳本
像 prebuild 這樣手動建置其他套件的腳本,會繞過 Turborepo 的相依性圖表。
// 錯誤 - 手動建置相依套件
{
"scripts": {
"prebuild": "cd ../../packages/types && bun run build && cd ../utils && bun run build",
"build": "next build"
}
}
然而,修復方式取決於是否已宣告 workspace 相依性:
-
若已宣告相依性(例如 package.json 中的
"@repo/types": "workspace:*"),請直接移除prebuild腳本。Turbo 的dependsOn: ["^build"]會自動處理建置順序。 -
若未宣告相依性,則
prebuild的存在是因為沒有相依關係時^build不會自動觸發。修復步驟為:- 在 package.json 新增相依性:
"@repo/types": "workspace:*" - 接著移除
prebuild腳本
- 在 package.json 新增相依性:
// 正確 - 宣告相依性,讓 turbo 處理建置順序
// package.json
{
"dependencies": {
"@repo/types": "workspace:*",
"@repo/utils": "workspace:*"
},
"scripts": {
"build": "next build"
}
}
// turbo.json
{
"tasks": {
"build": {
"dependsOn": ["^build"]
}
}
}
核心觀念: ^build 只會執行列為相依套件中的 build 任務。如果沒有宣告相依性 = 不會自動排序建置。
過於寬鬆的 globalDependencies
globalDependencies 會透過**全域雜湊(global hash)**影響所有套件中的所有任務 — 即使在 inputs 中使用否定匹配(negation globs),任務也無法排除特定檔案。請務必指定明確的範圍。
// 錯誤 - 範圍過大,影響所有雜湊值
{
"globalDependencies": ["**/.env.*local"]
}
// 較佳 - 移至任務層級的 inputs
{
"globalDependencies": [".env"],
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": ["dist/**"]
}
}
}
啟用 futureFlags.globalConfiguration 後此問題可獲得緩解,因為 global.inputs 檔案會直接合併至各任務的 inputs(而非納入全域雜湊)。任務即可排除特定檔案:
// 最佳 - 使用 global.inputs 並搭配個別任務排除規則
{
"futureFlags": { "globalConfiguration": true },
"global": {
"inputs": [".env"]
},
"tasks": {
"build": { "outputs": ["dist/**"] },
"lint": {
"inputs": ["$TURBO_DEFAULT$", "!$TURBO_ROOT$/.env"]
}
}
}
重複的任務設定
檢查跨任務之間是否有可以整合收攏的重複設定。Turborepo 支援共用設定模式。
// 錯誤 - 跨任務重複設定 env 與 inputs
{
"tasks": {
"build": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"test": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"dev": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"cache": false,
"persistent": true
}
}
}
// 較佳 - 使用 globalEnv 與 globalDependencies 設定共用項目
{
"globalEnv": ["API_URL", "DATABASE_URL"],
"globalDependencies": [".env*"],
"tasks": {
"build": {},
"test": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
何時使用全域(global)與任務層級(task-level):
globalEnv/globalDependencies- 影響所有任務,適用於真正全域共用的設定- 任務層級的
env/inputs- 僅在特定任務需要時使用
注意:大型 env 陣列「並非」反模式
即使 env 陣列很大(包含 50 個以上的變數),也不是問題。這通常代表使用者非常仔細地宣告了建置過程中所相依的環境變數。請勿將其標記為問題。
<!-- truncated for translation batch; full body continues in source -->





