UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Turborepo】turbo.jsonのオプションについて

Turborepoのチュートリアルで出てくるturbo.jsonのオプションについて調べた

チュートリアルは以下
Getting Started with Turborepo – Turborepo

オプションについては以下
Configuration – Turborepo

globalDependencies

グローバルハッシュの生成に影響あるファイルをリストにする

例えば.envtsconfig.jsonファイルといったルートディレクトリに配置するファイルを指定する

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    // ... omitted for brevity
  },
 
  "globalDependencies": [
    ".env", // contents will impact hashes of all tasks
    "tsconfig.json" // contents will impact hashes of all tasks
  ]
}

pipeline

プロジェクト内のタスクの出力を適切にスケジューリング、実行、キャッシュするための設定

オブジェクト内の各キーは、実行するタスクの名前

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

例えば以下のようにコマンドを入力すると各リポジトリのビルドが始まる

$ turbo run build
  • "dependsOn"はタスクを実行する前に実行する必要があるタスク依存関係を指定している
  • "outputs"はキャッシュするファイル群を指定する
  • "cache"スクリプトの結果をキャッシュしないようにTurborepo に指示している
  • "pesistentは長時間実行される開発サーバーであることを知らせるための設定で、他のタスクが依存しないようにできる(ないと他のタスクが始まらない)

一部だけ実行したい場合は--filterを使う

$ turbo dev --filter docs

モノレポのrootのpackage.jsonのscriptをturboから実行するには以下のように//#f<tasks>を設定する

{
  ...
  "pipeline": {
    ...
    "//#format": {
      "dependsOn": [],
      "outputs": ["dist/**/*"],
      "inputs": ["version.txt"]
    }
  }
}

これでrootのpackage.jsonで以下のように書かれたスクリプトを実行することができる

  "scripts": {
    ...
    "format": "prettier --write \"**/*.{ts,tsx,md}\""
  },

任意のワークスペースのタスクを実行したい時、かつ、任意のタスクを先に実行したい時は<workspace>#<task>を使う

例えば、webワークスペースのbuildを実行する前にuiワークスペースのlintを実行する場合、以下のように定義する

{
  ...
  "pipeline": {
    ...
    "web#build": {
      "dependsOn": ["@repo/ui#lint"]
    }
  }
}

この時、webはuiに依存しているのだが、その場合は@repo/をつける必要があった

TIPS

ドキュメントにtypecheckの高速化のTIPSがあった

dependencies-outside-of-a-task

例えば、webがuiに依存している場合で uiに変更があった場合、以下のようなタスクを定義してしまうと uiに変更があったにも関わらずwebはキャッシュを利用して成功してしまう

{
  ...
  "pipeline": {
    ...
    "typecheck": {}
  }
}

なので、webのtypecheckタスクの前にuiのtypecheckタスクを走らせたい

とはいえ、以下のようにしたとすると

{
  ...
  "pipeline": {
    ...
    "typecheck": {
      "dependsOn": ["^typecheck"]
    }
  }
}

並行実行されず、uiのtypecheckが終わるまでwebのtypecheckが開始されないため遅くなる

そこで、並行実行した上で、webがキャッシュミスを検知したらuiのtypecehckを開始するような設定にしたい

その場合は、以下のように設定すると良い

{
  ...
  "pipeline": {
    ...
    "topo": {
      "dependsOn": ["^topo"]
    }
    "typecheck": {
      "dependsOn": ["topo"]
    }
  }
}

typecheckが並列に実行される前に、topoが実行される

topoはダミーのタスクで、topo^がついているので依存関係の変更を確認しながら実行される

この時、uiに変更があるのでuiとwebのキャッシュは更新されるが、ダミーなので何もせずにすぐに終了する

topoが終わったら、次にtypecheckが実行されるがwebのtypecheck時にはキャッシュと差分があるので、キャッシュを使わずに再実行される

これで、依存関係の変更を検知しつつ並列的にtypecheckを実行することができる