リポジトリ
ドキュメント
コアコンセプト
タスクグラフ

タスクグラフ

前のセクションでは、Turborepoがturbo.jsonを使用して、タスクがどのように相互に関連しているかを表現する方法について説明しました。これらの関係はタスク間の依存関係と考えることができますが、より正式な名前があります。それがタスクグラフです。

Turborepoは、有向非巡回グラフ(DAG) (新しいタブで開きます)と呼ばれるデータ構造を使用して、リポジトリとそのタスクを理解します。グラフは「ノード」と「エッジ」で構成されています。タスクグラフでは、ノードはタスクであり、エッジはタスク間の依存関係です。*有向*グラフは、各ノードを接続するエッジに方向があることを示しているため、タスクAがタスクBを指している場合、タスクAはタスクBに依存していると言えます。エッジの方向は、どのタスクがどのタスクに依存しているかによって異なります。

たとえば、2つのパッケージ@repo/ui@repo/utilsに依存するアプリケーションapps/webを含むモノレポがあるとします。

my-monorepo
└─ apps
 └─ web
└─ packages
 └─ ui
 └─ utils

そして、^buildに依存するbuildタスクがあるとします。

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

Turborepoはこのようにタスクグラフを構築します。

Task graph visualization. The diagram has one node at the top named "apps/web" with two lines that connect to other nodes, "packages/ui" and "packages/utils" respectively.

中継ノード

タスクグラフを構築する際の課題は、ネストされた依存関係の処理です。たとえば、coreパッケージに依存するuiパッケージに依存するdocsアプリケーションがモノレポにあるとします。

my-monorepo
└─ apps
 └─ docs
└─ packages
 └─ ui
 └─ core

docs アプリと core パッケージにそれぞれ build タスクがあると仮定しましょう。ただし、ui パッケージには build タスクがありません。また、上記と同じ方法で build タスクを設定する turbo.json があり、"dependsOn": ["^build"] となっています。turbo run build を実行すると、何が起こると予想されますか?

Turborepo は、このタスクグラフを構築します。

A Task Graph visualization with a Transit Node. The diagram has one node at the top named "apps/doc" with a line that connects to a "packages/ui" node. This node does not have a "build" task. The "packages/ui" node has another line to a "packages/core" node that does have a "build" task.

このグラフは、一連のステップとして考えることができます。

  • docs アプリは ui のみに依存しています。
  • ui パッケージにはビルドスクリプトが**ありません**。
  • ui パッケージの*依存関係*には build スクリプトがあるため、タスクグラフにはそれらが含まれます。

Turborepo は、このシナリオでは ui パッケージをトランジットノードと呼びます。これは、独自の build スクリプトがないためです。build スクリプトがないため、Turborepo は ui パッケージに対して何も実行しませんが、依存関係を含める目的で、グラフの一部として残ります。

グラフにトランジットノードを含めなかった場合はどうなるでしょうか?

上記の例では、タスクグラフに ui ノード(とその依存関係)を含めています。これは、Turborepo が期待どおりにキャッシュミスすることを確認するための重要な違いです。

デフォルトでトランジットノードを**除外**する場合、core パッケージのソースコードの変更は、turbo run build に対する docs アプリのキャッシュを無効化せず、以前の core パッケージの反復からの古いコードを使用します。

エントリポイントとしてのトランジットノード

docs/ パッケージが build タスクを実装していない場合はどうなるでしょうか?この場合、何が起こると予想されますか?ui パッケージと core パッケージは、それでもビルドタスクを実行する必要がありますか?ここで*何か*が起こるべきでしょうか?

Turborepo のメンタルモデルは、タスクグラフ内のすべてのノードが同じであるというものです。言い換えれば、トランジットノードは、グラフ内のどこに表示されるかに関係なく、グラフに含まれます。このモデルは、予期しない結果をもたらす可能性があります。たとえば、build タスクを ^test に依存するように設定したとしましょう。

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

モノレポに多数のアプリと多数のパッケージがあるとします。すべてのパッケージに test タスクがありますが、1 つのアプリにのみ build タスクがあります。Turborepo のメンタルモデルでは、turbo run build を実行すると、アプリが build を実装していなくても、依存関係であるすべてのパッケージの test タスクがグラフに表示されます。