🌈
turbo.jsonの基本的な設定とワークスペースでの活用方法
はじめに
今回は、モノレポ(monorepo)開発で使用されるturbo.json
の基本的な設定と、複数パッケージ間の依存関係による実行順序について解説していきます。
turbo.jsonとは?
turbo.json
は、Turborepoというビルドシステムの設定ファイルです。複数のプロジェクトやパッケージを効率的に管理・ビルドするために使用されます。
基本的な設定例
まずは、典型的なturbo.json
の例を見てみましょう。
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"typecheck": {
"dependsOn": ["^typecheck"]
},
"dev": {
"persistent": true,
"cache": false
}
}
}
設定項目の解説
1. $schema
"$schema": "https://turbo.build/schema.json"
これは、VSCodeなどのエディタがこの設定ファイルを正しく理解するためのスキーマ定義です。
2. buildタスク
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
}
-
dependsOn
:^build
は依存しているパッケージのビルドを先に実行する -
outputs
: ビルド成果物の出力先を指定(.next/**
以下のファイル、ただしキャッシュは除外)
3. typecheckタスク
"typecheck": {
"dependsOn": ["^typecheck"]
}
-
dependsOn
: 依存パッケージの型チェックを先に実行する
4. devタスク
"dev": {
"persistent": true,
"cache": false
}
-
persistent
: 常時実行状態を維持 -
cache
: 開発中は常に最新のコードを反映させるためキャッシュを無効化
実践的なワークスペース構成
典型的なプロジェクト構成を見てみましょう。
my-monorepo/
├── packages/
│ ├── ui-components/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── shared-utils/
│ ├── package.json
│ └── tsconfig.json
├── apps/
│ └── web/
│ ├── package.json
│ └── tsconfig.json
└── turbo.json
各パッケージの設定と依存関係
packages/shared-utils/package.json
{
"name": "@my-monorepo/shared-utils",
"scripts": {
"typecheck": "tsc --noEmit",
"build": "tsc"
}
}
packages/ui-components/package.json
{
"name": "@my-monorepo/ui-components",
"dependencies": {
"@my-monorepo/shared-utils": "workspace:*" // shared-utilsへの依存を定義
},
"scripts": {
"typecheck": "tsc --noEmit",
"build": "tsc"
}
}
apps/web/package.json
{
"name": "@my-monorepo/web",
"dependencies": {
"@my-monorepo/ui-components": "workspace:*", // ui-componentsへの依存を定義
"@my-monorepo/shared-utils": "workspace:*" // shared-utilsへの依存を定義
},
"scripts": {
"typecheck": "tsc --noEmit",
"dev": "next dev",
"build": "next build"
}
}
パッケージ間の依存関係を理解する
package.jsonのdependencies
で定義された依存関係から、以下のような依存グラフが形成されます:
web → ui-components → shared-utils
web → shared-utils
この依存関係は以下のように形成されています。
-
web
はui-components
とshared-utils
の両方に依存(web/package.jsonのdependenciesで定義) -
ui-components
はshared-utils
に依存(ui-components/package.jsonのdependenciesで定義) -
shared-utils
は他のパッケージに依存していない
workspace:*
は同じモノレポ内のパッケージを参照することを示しています。
タスクの実行順序を理解する
turbo typecheck
を実行した場合、
{
"tasks": {
"typecheck": {
"dependsOn": ["^typecheck"]
}
}
}
この^typecheck
は「依存しているパッケージのtypecheckを先に実行する」という意味です。
実行順序
package.jsonで定義された依存関係に基づいて、以下の順序で実行されます。
- shared-utils: 他に依存していないため、最初に実行可能
-
ui-components:
shared-utils
の型チェックが完了するのを待ってから実行 -
web:
shared-utils
とui-components
両方の型チェックが完了するのを待ってから実行
なぜこの順序なのか?
-
shared-utils
は他のパッケージに依存していないため、最初に安全に実行できます -
ui-components
はshared-utils
を使用しているため、shared-utils
の型が正しいことを確認してから型チェックを行う必要があります -
web
は両方のパッケージを使用しているため、両方の型が正しいことを確認してから型チェックを行う必要があります
キャッシュの活用
Turborepoは実行結果をキャッシュします。
- 変更のないパッケージは前回の結果を再利用
- パッケージごとにキャッシュを管理
- チーム間でリモートキャッシュの共有も可能
まとめ
-
turbo.json
でタスクの依存関係と実行順序を制御 -
package.json
のdependencies
でパッケージ間の依存関係を定義 -
workspace:*
で同じモノレポ内のパッケージを参照 - 依存関係グラフに基づいて適切な実行順序が決定される
- キャッシュ機能により、ビルド時間を大幅に短縮可能
Discussion