Core Concepts

包图和任务图

了解 Turborepo 如何使用包图和任务图来理解您的 monorepo 结构和任务依赖关系。

包图

包图是由您的包管理器创建的 monorepo 结构。当您将内部包相互安装时,Turborepo 将自动识别这些依赖关系,以建立对您工作区的基础理解。

这为任务图奠定了基础,您将在任务图中定义任务之间的关系。

任务图

turbo.json 中,您可以表达任务之间的关系。您可以将这些关系视为任务之间的依赖关系,但我们有一个更正式的名称:任务图。

您可以使用 --graph 标志为您的任务生成任务图的可视化。

Turborepo 使用一种称为有向无环图 (DAG) 的数据结构来理解您的仓库及其任务。图由"节点"和"边"组成。在任务图中,节点是任务,边是任务之间的依赖关系。_有向_图表示连接每个节点的边都有方向,因此如果任务 A 指向任务 B,我们可以说任务 A 依赖于任务 B。边的方向取决于哪个任务依赖于哪个任务。

例如,假设您有一个 monorepo,其中 ./apps/web 中有一个应用程序,它依赖于两个包:@repo/ui@repo/utils

apps/
  web/
packages/
  ui/
  utils/

您还有一个依赖于 ^buildbuild 任务:

{
  "tasks": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}

Turborepo 将构建如下的任务图:

传递节点

构建任务图时的一个挑战是处理嵌套依赖关系。例如,假设您的 monorepo 有一个 docs 应用程序,它依赖于 ui 包,而 ui 包又依赖于 core 包:

apps/
  docs/
packages/
  ui/
  core/

假设 docs 应用程序和 core 包都有 build 任务,但 ui 包没有。您还有一个 turbo.json,它以与上面相同的方式配置 build 任务,使用 "dependsOn": ["^build"]。当您运行 turbo run build 时,您期望会发生什么?

Turborepo 将构建这个任务图:

您可以将此图视为一系列步骤:

  • docs 应用程序仅依赖于 ui
  • ui没有构建脚本。
  • ui 包的_依赖项_有 build 脚本,因此任务图知道要包含这些。

在这种情况下,Turborepo 将 ui 包称为传递节点,因为它没有自己的 build 脚本。由于它没有 build 脚本,Turborepo 不会为它执行任何操作,但为了包含其自身的依赖项,它仍然是图的一部分。

传递节点作为入口点

如果 docs/ 包没有实现 build 任务会怎样?在这种情况下您期望会发生什么?uicore 包是否仍应执行其构建任务?这里应该发生_任何事情_吗?

Turborepo 的心理模型是任务图中的所有节点都是相同的。换句话说,传递节点包含在图中,无论它们出现在图中的哪个位置。这种模型可能会产生意想不到的后果。例如,假设您已将 build 任务配置为依赖于 ^test

{
  "tasks": {
    "build": {
      "dependsOn": ["^test"]
    }
  }
}

假设您的 monorepo 有许多应用程序和许多包。所有包都有 test 任务,但只有一个应用程序有 build 任务。Turborepo 的心理模型说,当您运行 turbo run build 时,即使应用程序没有实现 build,作为依赖项的所有包的 test 任务也会出现在图中。