仓库
文档
核心概念
配置工作区

配置工作区

大多数单仓库可以在根目录中声明一个 turbo.json,其中包含适用于所有工作区的统一 管道。有时,单仓库可能包含需要以不同方式配置其任务的工作区。为了适应这种情况,从 1.8 版本开始,Turborepo 允许您使用任何工作区中的 turbo.json 来扩展根配置。这种灵活性使更多样化的应用程序和包能够共存,并允许工作区所有者维护专门的任务和配置,而不会影响单仓库中的其他应用程序和包。

工作原理

要覆盖根 turbo.json 中定义的任何任务的配置,请在单仓库的任何工作区中添加一个 turbo.json 文件,其中包含一个顶级的 extends

{
  "extends": ["//"],
  "pipeline": {
    "build": {
      // custom configuration for the build task in this workspace
    },
    // new tasks only available in this workspace
    "special-task": {},
  }
}

目前,extends 键的唯一有效值为 ["//"]// 是一个特殊名称,用于标识单仓库的根目录。

工作区中的配置可以覆盖 管道任务的任何配置。如果您不包含某个键,则该配置将从扩展的 turbo.json 中继承。

示例

为了说明,让我们看看一些用例。

不同的框架

假设您的单仓库有多个 Next.js (在新标签页中打开) 应用程序,以及一个 SvelteKit (在新标签页中打开) 应用程序。这两个框架都使用其各自的 package.json 中的 build 脚本创建其构建输出。您可以使用根目录中的单个 turbo.json 来配置 Turborepo 以运行这些任务,如下所示

{
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**"],
    }
  }
}

请注意,.next/**.svelte-kit/** 需要指定为 outputs,即使 Next.js 应用程序不会生成 .svelte-kit 目录,反之亦然。使用工作区配置,您可以改为在 apps/my-svelte-kit-app/turbo.json 中的 SvelteKit 工作区中添加自定义配置

{
  "extends": ["//"],
  "pipeline": {
    "build": {
      "outputs": [".svelte-kit/**"]
    }
  }
}

并从根配置中删除该配置

{
  "pipeline": {
    "build": {
-      "outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**"]
+      "outputs": [".next/**", "!.next/cache/**"]
    }
  }
}

这不仅使每个配置更易于阅读,而且将配置放置到更靠近使用位置的地方。

专门的任务

在另一个例子中,假设一个工作区中的 build 任务 dependsOn 一个 compile 任务。你可以将其全局声明为 dependsOn: ["compile"]。这意味着你的根目录 turbo.json 必须有一个空的 compile 任务条目

{
  "pipeline": {
    "build": {
      "dependsOn": ["compile"]
    },
    "compile": {}
  }
}

使用工作区配置,你可以将 compile 任务移动到 apps/my-custom-app/turbo.json 中,

{
  "extends": ["//"],
  "pipeline": {
    "build": {
      "dependsOn": ["compile"]
    },
    "compile": {}
  }
}

并从根目录中删除它。

{
  "pipeline": {
+    "build": {}
-    "build": {
-      "dependsOn": ["compile"]
-    },
-    "compile": {}
  }
}

现在,my-app 的所有者可以完全拥有他们的 build 任务,但继续继承在根目录中定义的任何其他任务。

与工作区特定任务的比较

乍一看,工作区配置可能听起来很像根目录 turbo.json 中的 workspace#task 语法。这些功能类似,但有一个显著区别:当你根目录 turbo.json 中声明一个工作区特定任务时,它会完全覆盖基线任务配置。使用工作区配置,任务配置将被合并。

考虑一个包含多个 Next.js 应用和一个 Sveltekit 应用的单体仓库的例子。如果没有工作区特定任务,你可能会像这样配置你的根目录 turbo.json

{
  "pipeline": {
    "build": {
      "outputMode": "hash-only",
      "inputs": ["src/**"],
      "outputs": [".next/**", "!.next/cache/**"],
    },
    "my-sveltekit-app#build": {
      "outputMode": "hash-only", // must duplicate this
      "inputs": ["src/**"], // must duplicate this
      "outputs": [".svelte-kit/**"]
    }
  }
}

在这个例子中,my-sveltekit-app#build 完全覆盖了 Sveltekit 应用的 build,因此 outputModeinputs 也需要被复制。

使用工作区配置,outputModeinputs 是被继承的,因此你不需要复制它们。你只需要覆盖 outputs my-sveltekit-app 配置。

虽然没有计划删除工作区特定任务配置,但我们预计工作区配置可以用于大多数用例。

限制

虽然总体思路与根目录 turbo.json 相同,但工作区配置有一套护栏,可以防止工作区创建令人困惑的情况。这些护栏列在这里是为了明确它们是故意的,而不是偶然的

  • 工作区配置不能使用 workspace#task 语法 作为管道条目

    workspace 是根据配置的位置推断出来的,无法更改另一个工作区的配置。例如,在 'my-nextjs-app' 的工作区配置中

    {
      "pipeline": {
        "my-nextjs-app#build": {
          // ❌ This is not allowed. Even though it's
          // referencing the correct workspace, "my-nextjs-app"
          // is inferred, and we don't need to specify it again.
          // This syntax also has different behavior, so we do not want to allow it.
          // (see "Comparison to Workspace-specific tasks" section)
        },
        "my-sveltekit-app#build": {
          // ❌ Changing configuration for the "my-sveltekit-app" workspace
          // from Workspace Configuration in "my-nextjs-app" is not allowed.
        },
        "build": {
          // ✅ just use the task name!
        },
      }
    }

    请注意, build 任务仍然可以依赖于工作区特定任务

    {
      "pipeline": {
        "build": {
          // ✅ It's still ok to have workspace#task in dependsOn!
          "dependsOn": ["some-pkg#compile"]
        },
      }
    }
  • 工作区配置不能覆盖 pipeline 键之外的任何内容。

    例如,无法覆盖 globalEnvglobalDependencies。我们预计单体仓库所有者应该绝对控制这一点,如果此配置不是真正全局的,则不应该以这种方式配置。

  • 根目录 turbo.json 不能使用 extends 键。

    为了避免在工作区上创建循环依赖关系,根目录 turbo.json 不能从任何东西继承。

如果你有任何这些用例,请 提交一个问题 (opens in a new tab)

故障排除

在大型单体仓库中,有时很难理解 Turborepo 如何解释你的配置。为了帮助你,我们在 Dry Run 输出中添加了 resolvedTaskDefinition。例如,如果你运行 turbo run build --dry-run,输出将包括在运行 build 任务之前考虑的所有 turbo.json 配置的组合。