Configuration

包配置

使用包配置为 monorepo 中的特定包自定义 turbo.json 配置

许多 monorepo 可以在根目录中声明一个 turbo.json,其中包含适用于所有包的 任务描述。但是,有时 monorepo 可能包含需要以不同方式配置其任务的包。

为了适应这种情况,Turborepo 允许您在任何包中使用 turbo.json 扩展根配置。这种灵活性使更多样化的应用程序和包能够在工作空间中共存,并允许包所有者维护专门的任务和配置,而不会影响 monorepo 的其他应用程序和包。

工作原理

要覆盖根 turbo.json 中定义的任何任务的配置,请在 monorepo 的任何包中添加一个带有顶级 extends 键的 turbo.json 文件:

{
  "extends": ["//"],
  "tasks": {
    "build": {
      // 此包中构建任务的自定义配置
    },
    "special-task": {} // 此包特有的新任务
  }
}

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

包中的配置可以覆盖 任务的任何配置。任何未包含的键都从扩展的 turbo.json 继承。

示例

一个工作空间中的不同框架

假设您的 monorepo 有多个 Next.js 应用程序和一个 SvelteKit 应用程序。两个框架都在各自的 package.json 中使用 build 脚本创建构建输出。您_可以_配置 Turborepo 在根目录使用单个 turbo.json 运行这些任务,如下所示:

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

请注意,即使 Next.js 应用程序不生成 .svelte-kit 目录,反之亦然,也需要将 .next/**.svelte-kit/** 都指定为 outputs

使用包配置,您可以在 apps/my-svelte-kit-app/turbo.json 中的 SvelteKit 包中添加自定义配置:

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

并从根配置中删除 SvelteKit 特定的 outputs

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

这不仅使每个配置更易于阅读,还将配置放在更接近使用它的地方。

专门的任务

在另一个示例中,假设一个包中的 build 任务 dependsOn 一个 compile 任务。您可以将其普遍声明为 dependsOn: ["compile"]。这意味着您的根 turbo.json 必须有一个空的 compile 任务条目:

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

使用包配置,您可以将该 compile 任务移动到 apps/my-custom-app/turbo.json 中:

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

并从根目录中删除它:

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

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

与包特定任务的比较

乍一看,包配置可能听起来很像根 turbo.json 中的 package#task 语法。这些功能相似,但有一个重要区别:当您在根 turbo.json 中声明包特定任务时,它_完全_覆盖基线任务配置。使用包配置,任务配置会被合并。

再次考虑具有多个 Next.js 应用程序和一个 Sveltekit 应用程序的 monorepo 示例。使用包特定任务,您可能会这样配置根 turbo.json

{
  "tasks": {
    "build": {
      "outputLogs": "hash-only",
      "inputs": ["src/**"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "my-sveltekit-app#build": {
      "outputLogs": "hash-only", // 必须重复这个
      "inputs": ["src/**"], // 必须重复这个
      "outputs": [".svelte-kit/**"]
    }
  }
}

在此示例中,my-sveltekit-app#build 完全覆盖了 Sveltekit 应用程序的 build,因此 outputLogsinputs 也需要重复。

使用包配置,outputLogsinputs 是继承的,因此您不需要重复它们。您只需要在 my-sveltekit-app 配置中覆盖 outputs

虽然没有计划删除包特定任务配置,但我们期望包配置可以用于大多数用例。

边界标签 ::badge实验性

包配置也用于为边界声明标签。为此,请在您的 turbo.json 中添加 tags 字段:

{
+ "tags": ["my-tag"],
  "extends": ["//"],
  "tasks": {
    "build": {
      "dependsOn": ["compile"]
    },
    "compile": {}
  }
}

从那里,您可以定义标签可以拥有哪些依赖项或依赖者的规则。查看 边界文档 了解更多详细信息。

限制

虽然总体思路与根 turbo.json 相同,但包配置带有一组防护措施,可以防止包创建潜在的混乱情况。

包配置不能使用 the workspace#task 语法 作为任务条目

package 是根据配置的位置推断的,不可能更改另一个包的配置。例如,在 my-nextjs-app 的包配置中:

{
  "tasks": {
    "my-nextjs-app#build": {
      // ❌ 这是不允许的。即使它引用了正确的包,
      // "my-nextjs-app" 是推断的,我们不需要再次指定它。
      // 这种语法也有不同的行为,所以我们不想允许它。
      // (参见"与包特定任务的比较"部分)
    },
    "my-sveltekit-app#build": {
      // ❌ 从 "my-nextjs-app" 的包配置中更改 "my-sveltekit-app" 包的配置是不允许的。
    },
    "build": {
      // ✅ 只需使用任务名称!
    }
  }
}

请注意,build 任务仍然可以依赖于包特定任务:

{
  "tasks": {
    "build": {
      "dependsOn": ["some-pkg#compile"]    }
  }
}

包配置只能覆盖 tasks 键中的值

在包配置中不可能覆盖 全局配置,如 globalEnvglobalDependencies。需要在包配置中更改的配置不是真正的全局配置,应该以不同的方式配置。

根 turbo.json 不能使用 extends

为了避免在包上创建循环依赖,根 turbo.json 不能从任何东西扩展。extends 键将被忽略。

故障排除

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