mcpField
T
turborepo

turborepo

github.com/timelessco開発51 回インストール
リポジトリ

turborepo について

JavaScript と TypeScript のモノレポで Turborepo を使う方法をまとめたスキルです。タスクの依存関係、キャッシュ、ワークスペース設定、CI の運用を扱い、複数パッケージを管理する開発者向けです。

主な機能

  1. 01依存関係に基づくタスクパイプライン設定
  2. 02ローカル・リモートキャッシュの利用
  3. 03パッケージや変更によるタスク選択
  4. 04デプロイ用ワークスペースの絞り込み
  5. 05ワークスペースパッケージの設定

活用シーン

  1. 01モノレポの反復ビルドの高速化
  2. 02変更されたパッケージだけでの CI 実行
  3. 03アプリ別 Docker ビルド入力の準備
  4. 04ビルド・テスト・lint タスクの調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/timelessco/recollect --skill turborepo

インストール後、Claude Code で/turborepoを入力して読み込まれたか確認します。

詳細

Turborepo スキル

Turborepo は、Rust で記述された、JavaScript および TypeScript のモノレポ向けに最適化された高性能ビルドシステムです。インテリジェントなキャッシュ、タスクのオーケストレーション、リモート実行機能を備え、開発ワークフローを大幅に高速化します。

リファレンス

https://turborepo.com/llms.txt

このスキルを使用するタイミング

次のような場合にこのスキルを使用します。

  • 複数のパッケージを含む新しいモノレポをセットアップする
  • 既存のモノレポのビルドパフォーマンスを最適化する
  • パッケージ間のタスクパイプラインを実装する
  • インテリジェントなキャッシュ戦略を設定する
  • チーム向けにリモートキャッシュをセットアップする
  • 依存関係を考慮してタスクをオーケストレーションする
  • モノレポを CI/CD パイプラインに統合する
  • Lerna、Nx、その他のモノレポツールから移行する
  • マイクロフロントエンドや共有ライブラリを構築する
  • ワークスペースの依存関係を管理する

主な概念

1. モノレポアーキテクチャ

Turborepo は、単一のリポジトリ内のパッケージにコードを整理します。

  • ルートパッケージ:ワークスペース設定を含みます
  • 内部パッケージ:共有ライブラリ、ユーティリティ、設定
  • アプリケーション:フロントエンドアプリ、バックエンドサービスなど
  • ワークスペース:npm/yarn/pnpm のワークスペース設定
2. タスクパイプライン

タスクは依存関係グラフに沿って整理されます。

  • タスクの依存関係:実行順序を定義します(テストの前にビルド)
  • パッケージの依存関係:内部パッケージ間の関係を考慮します
  • 並列実行:独立したタスクを同時に実行します
  • トポロジカル順序:依存関係に沿った正しい順序でタスクを実行します
3. インテリジェントなキャッシュ

Turborepo は入力に基づいてタスクの出力をキャッシュします。

  • ローカルキャッシュ:出力をローカルマシンに保存します
  • リモートキャッシュ:チームや CI 間でキャッシュを共有します(Vercel またはカスタム)
  • コンテンツベースのハッシュ化:入力が変更された場合にのみ再実行します
  • キャッシュの復元:キャッシュからタスクを即座に完了します
4. タスクの出力

キャッシュ対象を定義します。

  • ビルド成果物(dist/, build/)
  • テスト結果
  • 生成ファイル
  • 型定義

インストール

前提条件
# Requires Node.js 18+ and a package manager
node --version # v18.0.0+
グローバルインストール
# npm
npm install turbo --global

# yarn
yarn global add turbo

# pnpm
pnpm add turbo --global

# bun
bun add turbo --global
プロジェクトごとのインストール
# npm
npm install turbo --save-dev

# yarn
yarn add turbo --dev

# pnpm
pnpm add turbo --save-dev

# bun
bun add turbo --dev

プロジェクトのセットアップ

新しいモノレポを作成する

公式のサンプルを使用します。

npx create-turbo@latest

対話形式のプロンプトで、次の項目を確認されます。

  • プロジェクト名
  • パッケージマネージャー(npm/yarn/pnpm/bun)
  • サンプルテンプレートの選択
手動でのセットアップ

1. ワークスペースを初期化する:

// package.json (root)
{
	"name": "my-turborepo",
	"private": true,
	"workspaces": ["apps/*", "packages/*"],
	"scripts": {
		"build": "turbo run build",
		"dev": "turbo run dev",
		"test": "turbo run test",
		"lint": "turbo run lint"
	},
	"devDependencies": {
		"turbo": "latest"
	}
}

2. ディレクトリ構造を作成する:

my-turborepo/
├── apps/
│   ├── web/              # Next.js app
│   └── docs/             # Documentation site
├── packages/
│   ├── ui/               # Shared UI components
│   ├── config/           # Shared configs (ESLint, TS)
│   └── tsconfig/         # Shared TypeScript configs
├── turbo.json            # Turborepo configuration
└── package.json          # Root package.json

3. turbo.json を作成する:

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

設定(turbo.json)

基本構造
{
	"$schema": "https://turbo.build/schema.json",
	"globalDependencies": [".env", "tsconfig.json"],
	"globalEnv": ["NODE_ENV"],
	"pipeline": {
		// Task definitions
	}
}
パイプラインの設定

依存関係のあるタスク:

{
	"pipeline": {
		"build": {
			"dependsOn": ["^build"],
			"outputs": ["dist/**", ".next/**"],
			"env": ["NODE_ENV", "API_URL"]
		}
	}
}

主なプロパティ:

  • dependsOn:先に実行するタスク
    • ["^build"]:依存パッケージの build を先に実行する
    • ["build"]:自身の build を先に実行する
    • ["^build", "lint"]:依存パッケージの build と自身の lint を実行する
  • outputs:キャッシュするファイル/ディレクトリ
  • inputs:入力の検出を上書きします(デフォルト:追跡対象のすべてのファイル)
  • cache:キャッシュを有効化/無効化します(デフォルト:true)
  • env:出力に影響する環境変数
  • persistent:タスクを実行し続けます(開発サーバー向け)
  • outputMode:出力の表示方法を制御します
タスク依存関係のパターン

トポロジカル(^):

{
	"build": {
		"dependsOn": ["^build"] // Run dependencies' build first
	}
}

通常:

{
	"deploy": {
		"dependsOn": ["build", "test"] // Run own build and test first
	}
}

組み合わせ:

{
	"test": {
		"dependsOn": ["^build", "lint"] // Deps' build, then own lint
	}
}
出力モード
{
	"pipeline": {
		"build": {
			"outputMode": "full" // Show all output
		},
		"dev": {
			"outputMode": "hash-only" // Show cache hash only
		},
		"test": {
			"outputMode": "new-only" // Show new output only
		},
		"lint": {
			"outputMode": "errors-only" // Show errors only
		}
	}
}
環境変数

グローバル環境変数:

{
	"globalEnv": ["NODE_ENV", "CI"],
	"globalDependencies": [".env", ".env.local"]
}

タスクごとの環境変数:

{
	"pipeline": {
		"build": {
			"env": ["NEXT_PUBLIC_API_URL", "DATABASE_URL"],
			"passThroughEnv": ["CUSTOM_VAR"] // Pass without hashing
		}
	}
}

コマンド

turbo run

パッケージ全体でタスクを実行します。

# Run build in all packages
turbo run build

# Run multiple tasks
turbo run build test lint

# Run in specific packages
turbo run build --filter=web
turbo run build --filter=@myorg/ui

# Run in packages matching pattern
turbo run build --filter='./apps/*'

# Force execution (skip cache)
turbo run build --force

# Run from specific directory
turbo run build --filter='[./apps/web]'

# Run with dependencies
turbo run build --filter='...^web'

# Parallel execution control
turbo run build --concurrency=3
turbo run build --concurrency=50%

# Continue on error
turbo run test --continue

# Dry run
turbo run build --dry-run

# Output control
turbo run build --output-logs=new-only
turbo run build --output-logs=hash-only
turbo run build --output-logs=errors-only
turbo run build --output-logs=full
turbo prune

モノレポのサブセットを作成します。

# Prune for specific app
turbo prune --scope=web

# Prune with Docker
turbo prune --scope=api --docker

# Output to custom directory
turbo prune --scope=web --out-dir=./deploy

用途:

  • Docker ビルド(必要なパッケージのみを含める)
  • 特定のアプリをデプロイする
  • CI/CD のコンテキストサイズを削減する
turbo gen

モノレポ内でコードを生成します。

# Generate new package
turbo gen workspace

# Generate from custom generator
turbo gen my-generator

# List available generators
turbo gen --list
turbo link

ローカルリポジトリをリモートキャッシュにリンクします。

# Link to Vercel
turbo link

# Unlink
turbo unlink
turbo login

Vercel で認証します。

turbo login
turbo ls

モノレポ内のパッケージを一覧表示します。

# List all packages
turbo ls

# JSON output
turbo ls --json

フィルタリング

パッケージ名でフィルタリング
# Single package
turbo run build --filter=web

# Multiple packages
turbo run build --filter=web --filter=api

# Scoped package
turbo run build --filter=@myorg/ui
パターンでフィルタリング
# All apps
turbo run build --filter='./apps/*'

# Pattern matching
turbo run build --filter='*-ui'
ディレクトリでフィルタリング
# From specific directory
turbo run build --filter='[./apps/web]'
Git でフィルタリング
# Changed since main
turbo run build --filter='[main]'

# Changed since HEAD~1
turbo run build --filter='[HEAD~1]'

# Changed in working directory
turbo run test --filter='...[HEAD]'
依存関係でフィルタリング
# Package and its dependencies
turbo run build --filter='...web'

# Package's dependencies only
turbo run build --filter='...^web'

# Package and its dependents
turbo run test --filter='ui...'

# Package's dependents only
turbo run test --filter='^ui...'

キャッシュ戦略

ローカルキャッシュ

デフォルトで有効で、./node_modules/.cache/turbo に保存されます

キャッシュの動作:

{
	"pipeline": {
		"build": {
			"outputs": ["dist/**"], // Cache dist directory
			"cache": true // Enable caching (default)
		},
		"dev": {
			"cache": false // Disable for dev servers
		}
	}
}

キャッシュをクリアする:

# Clear Turbo cache
rm -rf ./node_modules/.cache/turbo

# Or use turbo command
turbo run build --force # Skip cache for this run
リモートキャッシュ

チームや CI 間でキャッシュを共有します:

1. Vercel にリンクする(推奨):

turbo login
turbo link

2. カスタムリモートキャッシュ:

// .turbo/config.json
{
	"teamid": "team_123",
	"apiurl": "https://cache.example.com",
	"token": "your-token"
}

メリット:

  • チーム間でビルドを共有
  • CI/CD を高速化
  • ビルドの一貫性を確保
  • コンピューティングコストを削減
キャッシュシグネチャ

以下の場合、キャッシュが無効になります:

  • ソースファイルが変更された場合
  • 依存関係が変更された場合
  • 環境変数が変更された場合(指定されている場合)
  • グローバル依存関係が変更された場合
  • タスク設定が変更された場合

入力を制御する:

{
	"pipeline": {
		"build": {
			"inputs": ["src/**/*.ts", "!src/**/*.test.ts"],
			"env": ["NODE_ENV"]
		}
	}
}

ワークスペースのパターン

パッケージの種類

1. 内部パッケージ(packages/*):

// packages/ui/package.json
{
	"name": "@myorg/ui",
	"version": "0.0.0",
	"main": "./dist/index.js",
	"types": "./dist/index.d.ts",
	"scripts": {
		"build": "tsc",
		"dev": "tsc --watch",
		"lint": "eslint ."
	}
}

2. アプリケーション(apps/*):

// apps/web/package.json
{
	"name": "web",
	"version": "1.0.0",
	"private": true,
	"dependencies": {
		"@myorg/ui": "*",
		"next": "latest"
	},
	"scripts": {
		"dev": "next dev",
		"build": "next build",
		"start": "next start"
	}
}
依存関係の管理

ワークスペースプロトコル(pnpm/yarn):

{
	"dependencies": {
		"@myorg/ui": "workspace:*"
	}
}

バージョンプロトコル(npm):

{
	"dependencies": {
		"@myorg/ui": "*"
	}
}
共有設定

ESLint 設定パッケージ:

// packages/eslint-config/index.js
module.exports = {
	extends: ["next", "prettier"],
	rules: {
		// shared rules
	},
};

TypeScript 設定パッケージ:

// packages/tsconfig/base.json
{
	"compilerOptions": {
		"strict": true,
		"esModuleInterop": true,
		"skipLibCheck": true,
		"forceConsistentCasingInFileNames": true
	}
}

使用方法:

// apps/web/tsconfig.json
{
	"extends": "@myorg/tsconfig/base.json",
	"compilerOptions": {
		"jsx": "preserve"
	}
}

CI/CD との統合

GitHub Actions
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 18

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npx turbo run build
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: ${{ secrets.TURBO_TEAM }}

      - name: Test
        run: npx turbo run test
GitLab CI
image: node:18

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
    - .turbo/

build:
  stage: build
  script:
    - npm install
    - npx turbo run build
  variables:
    TURBO_TOKEN: $TURBO_TOKEN
    TURBO_TEAM: $TURBO_TEAM
Docker
FROM node:18-alpine AS base

# Prune workspace
FROM base AS builder
RUN npm install -g turbo
COPY . .
RUN turbo prune --scope=web --docker

# Install dependencies
FROM base AS installer
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/package-lock.json ./package-lock.json
RUN npm install

# Build
COPY --from=builder /app/out/full/ .
RUN npx turbo run build --filter=web

# Runner
FROM base AS runner
COPY --from=installer /app/apps/web/.next/standalone ./
COPY --from=installer /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer /app/apps/web/public ./apps/web/public

CMD node apps/web/server.js
最適化のヒント
  1. CI でリモートキャッシュを使用する:
env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
  1. node_modules をキャッシュする:
- uses: actions/cache@v3
  with:
    path: node_modules
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
  1. 影響を受けるタスクのみを実行する:
turbo run build test --filter='...[origin/main]'

フレームワークとの統合

Next.js
// apps/web/package.json
{
	"name": "web",
	"scripts": {
		"dev": "next dev",
		"build": "next build",
		"start": "next start"
	},
	"dependencies": {
		"next": "latest",
		"react": "latest"
	}
}

turbo.json:

{
	"pipeline": {
		"build": {
			"outputs": [".next/**", "!.next/cache/**"]
		},
		"dev": {
			"cache": false,
			"persistent": true
		}
	}
}
Vite
{
	"pipeline": {
		"build": {
			"dependsOn": ["^build"],
			"outputs": ["dist/**"]
		},
		"dev": {
			"cache": false,
			"persistent": true
		}
	}
}
NuxtJS
{
	"pipeline": {
		"build": {
			"outputs": [".output/**", ".nuxt/**"]
		},
		"dev": {
			"cache": false,
			"persistent": true
		}
	}
}

開発ツールとの統合

TypeScript
{
	"pipeline": {
		"build": {
			"dependsOn": ["^build"],
			"outputs": ["dist/**", "*.tsbuildinfo"]
		},
		"typecheck": {
			"dependsOn": ["^build"]
		}
	}
}
ESLint
{
	"pipeline": {
		"lint": {
			"dependsOn": ["^build"],
			"outputs": []
		}
	}
}
Jest / Vitest
{
	"pipeline": {
		"test": {
			"dependsOn": ["build"],
			"outputs": ["coverage/**"],
			"cache": true
		}
	}
}
Prisma
{
	"pipeline": {
		"db:generate": {
			"cache": false
		},
		"db:push": {
			"cache": false
		}
	}
}

ベストプラクティス

1. モノレポを構成する
my-monorepo/
├── apps/                    # Applications
│   ├── web/                # Frontend app
│   ├── api/                # Backend API
│   └── docs/               # Documentation
├── packages/               # Shared packages
│   ├── ui/                 # UI components
│   ├── config/             # Shared configs
│   ├── utils/              # Utilities
│   └── tsconfig/           # TS configs
├── tooling/                # Development tools
│   ├── eslint-config/
│   └── prettier-config/
└── turbo.json
2. タスクの依存関係を明確に定義する
{
	"pipeline": {
		"build": {
			"dependsOn": ["^build"]
		},
		"test": {
			"dependsOn": ["build"]
		},
		"lint": {
			"dependsOn": ["^build"]
		},
		"deploy": {
			"dependsOn": ["build", "test", "lint"]
		}
	}
}
3. キャッシュ設定を最適化する
  • ソースファイルではなく、ビルド出力をキャッシュする
  • 生成されるすべてのファイルを出力に含める
  • キャッシュディレクトリを除外する(例:.next/cache)
  • 開発サーバーのキャッシュを無効にする
{
	"pipeline": {
		"build": {
			"outputs": [
				"dist/**",
				".next/**",
				"!.next/cache/**",
				"storybook-static/**"
			]
		},
		"dev": {
			"cache": false,
			"persistent": true
		}
	}
}
4. 環境変数を適切に使用する
{
	"globalEnv": ["NODE_ENV", "CI"],
	"pipeline": {
		"build": {
			"env": ["NEXT_PUBLIC_API_URL"],
			"passThroughEnv": ["DEBUG"] // Don't affect cache
		}
	}
}
5. リモートキャッシュを活用する
  • すべてのチームメンバーに対して有効にする
  • CI/CD で設定する
  • ビルド時間を大幅に短縮
  • 大規模なチームでは特に効果的
6. フィルターを効果的に使用する
# Build only changed packages
turbo run build --filter='...[origin/main]'

# Build specific app with dependencies
turbo run build --filter='...web'

# Test only affected packages
turbo run test --filter='...[HEAD^1]'
7. スクリプトを一貫した方法で整理する

ルートの package.json:

{
	"scripts": {
		"build": "turbo run build",
		"dev": "turbo run dev",
		"lint": "turbo run lint",
		"test": "turbo run test",
		"clean": "turbo run clean && rm -rf node_modules"
	}
}
8. 永続的なタスクを処理する
{
	"pipeline": {
		"dev": {
			"cache": false,
			"persistent": true // Keeps running
		}
	}
}

よくあるパターン

フルスタックアプリケーション
apps/
├── web/          # Next.js frontend
│   └── package.json
├── api/          # Express backend
│   └── package.json
└── mobile/       # React Native
    └── package.json

packages/
├── ui/           # Shared UI components
├── database/     # Database client/migrations
├── types/        # Shared TypeScript types
└── config/       # Shared configs
共有コンポーネントライブラリ
packages/
├── ui/                    # Component library
│   ├── src/
│   ├── package.json
│   └── tsconfig.json
└── ui-docs/              # Storybook
    ├── .storybook/
    ├── stories/
    └── package.json
マイクロフロントエンド
apps/
├── shell/        # Container app
├── dashboard/    # Dashboard MFE
└── settings/     # Settings MFE

packages/
├── shared-ui/    # Shared components
└── router/       # Routing logic

トラブルシューティング

キャッシュの問題

問題:キャッシュが使われるはずなのに、タスクで使用されない

# Check what's causing cache miss
turbo run build --dry-run=json

# Force rebuild
turbo run build --force

# Clear cache
rm -rf ./node_modules/.cache/turbo

問題:キャッシュが大きすぎる

# Limit cache size in turbo.json
{
	"cacheDir": ".turbo",
	"cacheSize": "50gb"
}
依存関係の問題

問題:内部パッケージが見つからない

# Ensure workspace is set up correctly
npm install

# Check package names match
npm ls @myorg/ui

# Rebuild dependencies
turbo run build --filter='...web'
タスク実行の問題

問題:タスクの実行順序が正しくない

  • dependsOn の設定を確認する
  • 依存タスクには ^task を使用する
  • タスク名が package.json のスクリプトと一致することを確認する

問題:開発サーバーが起動しない

{
	"pipeline": {
		"dev": {
			"cache": false,
			"persistent": true // Add this
		}
	}
}
パフォーマンスの問題

問題:ビルドに時間がかかりすぎる

# Run with concurrency limit
turbo run build --concurrency=2

# Use filters to build less
turbo run build --filter='...[origin/main]'

# Check for unnecessary dependencies
turbo run build --dry-run

問題:リモートキャッシュが機能しない

# Verify authentication
turbo link

# Check environment variables
echo $TURBO_TOKEN
echo $TURBO_TEAM

# Test connection
turbo run build --output-logs=hash-only

移行ガイド

Lerna からの移行
  1. Lerna を Turborepo に置き換える:
npm uninstall lerna
npm install turbo --save-dev
  1. lerna.json を turbo.json に変換する:
{
	"pipeline": {
		"build": {
			"dependsOn": ["^build"]
		}
	}
}
  1. スクリプトを更新する:
{
	"scripts": {
		"build": "turbo run build",
		"test": "turbo run test"
	}
}
Nx からの移行
  1. Turborepo をインストールする:
npm install turbo --save-dev
  1. nx.json を turbo.json に変換する:
  • targetDefaults を pipeline にマッピングする
  • dependsOn の構文を変換する
  • キャッシュを設定する
  1. ワークスペース設定を更新する
  2. CI/CD スクリプトを移行する

リソース

実装チェックリスト

Turborepo をセットアップする際は、次の手順を実施します。

  • Turborepo をグローバルまたはプロジェクト単位でインストールする
  • ワークスペース構造(apps/, packages/)をセットアップする
  • パイプライン構成を含む turbo.json を作成する
  • タスクの依存関係(build、test、lint)を定義する
  • 各タスクのキャッシュ出力を構成する
  • グローバル依存関係と環境変数をセットアップする
  • リモートキャッシュ(Vercel またはカスタム)に接続する
  • CI/CD 統合を構成する
  • 大規模リポジトリ向けのフィルタリング戦略を追加する
  • チーム向けにモノレポ構造をドキュメント化する
  • コード生成(turbo gen)をセットアップする
  • turbo prune を使用した Docker ビルドを構成する
  • ローカルでキャッシュの動作をテストする
  • CI でリモートキャッシュを確認する
  • 並行処理の設定を最適化する

コメント