Turborepo 2.x × pnpm WorkspacesでモノレポCI/CDを最適化する完全ガイド

Turborepo 2.xとpnpm 9.x Workspacesによるモノレポ構築術を徹底解説。キャッシュ戦略・GitHub Actions連携を今すぐ実践しよう。

Turborepo 2.x × pnpm Workspaces完全ガイド|2026年モノレポCI/CD最適化

2026年現在、フロントエンドからバックエンドまで複数パッケージを一元管理するモノレポは、エンタープライズ開発の主流になりつつあります。しかし「モノレポを導入したはいいが、CIが遅い」「ビルドの依存関係が複雑で管理しきれない」といった課題を抱えているチームも多いのではないでしょうか。

本記事では、Turborepo 2.x(2026年3月時点の最新安定版 v2.3)pnpm 9.x Workspaces を組み合わせた実践的なCI/CD最適化手法を、具体的な設定例と共に解説します。


Turborepo 2.xの主要アップデートと2026年の位置づけ

2025年後半にリリースされたTurborepo 2系では、従来の1系から以下の点が大きく刷新されました。

機能v1.x(旧)v2.x(2026年最新)
タスクグラフエンジンJSON定義のみturbo.tsでTypeScript定義対応
リモートキャッシュVercel専用Self-hosted(S3/GCS)+ Vercel両対応
Watch Mode実験的安定版に昇格、incremental build対応
パッケージマネージャーnpm/yarn/pnpmpnpm優先設計(catalog機能完全対応)
ターミナルUIなしTUI(Terminal UI)標準搭載
Rust製コア一部フルRust実装でCPU使用率30%改善

[要確認] Turborepo v2.3のリリース時期・バージョン番号・「フルRust実装でCPU使用率30%改善」という具体的な数値は、執筆時点の情報をもとに記載しています。公式リリースノートで最新情報をご確認ください。

とくに注目すべきは、turbo.tsによるTypeScriptネイティブな設定ファイルのサポートです。これにより、静的型チェックを効かせながらタスクグラフを定義できるようになりました。

// turbo.ts(v2.x 新形式)
import type { TurboConfig } from 'turbo';

const config: TurboConfig = {
  ui: 'tui',
  tasks: {
    build: {
      dependsOn: ['^build'],
      outputs: ['dist/**', '.next/**', '!.next/cache/**'],
      env: ['NODE_ENV', 'API_URL'],
    },
    test: {
      dependsOn: ['build'],
      outputs: ['coverage/**'],
      cache: true,
    },
    lint: {
      outputs: [],
      cache: true,
    },
    dev: {
      persistent: true,
      cache: false,
    },
  },
};

export default config;

pnpm 9.x Workspaces × Catalog機能の実践設計

2026年時点でpnpm 9系が安定版となり、特にCatalog機能がモノレポ管理を劇的に改善しました。Catalogとは、ワークスペース全体で使用する依存パッケージのバージョンを一元管理する仕組みです。

ディレクトリ構成例

my-monorepo/
├── apps/
│   ├── web/          # Next.js 15アプリ
│   └── api/          # Hono + Cloudflare Workers
├── packages/
│   ├── ui/           # 共通UIコンポーネント
│   ├── config/       # ESLint・TypeScript共通設定
│   └── database/     # Prisma スキーマ・クライアント
├── pnpm-workspace.yaml
├── turbo.ts
└── package.json

pnpm-workspace.yamlのCatalog設定

# pnpm-workspace.yaml(pnpm 9.x Catalog機能)
packages:
  - 'apps/*'
  - 'packages/*'

catalog:
  # フレームワーク
  react: ^19.1.0
  react-dom: ^19.1.0
  next: ^15.3.0
  hono: ^4.7.0
  
  # ビルドツール
  typescript: ^5.8.0
  vite: ^6.2.0
  
  # テスト
  vitest: ^3.1.0
  '@testing-library/react': ^16.3.0
  
  # 共通ユーティリティ
  zod: ^3.24.0
  '@tanstack/react-query': ^5.70.0

各パッケージのpackage.jsonではcatalog:プロトコルで参照します。

{
  "name": "@myapp/web",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:",
    "next": "catalog:",
    "@tanstack/react-query": "catalog:",
    "zod": "catalog:"
  }
}

これにより、全パッケージのReactバージョンをpnpm-workspace.yaml一か所だけ変更すれば一括更新できます。


リモートキャッシュ戦略:Self-hosted S3 vs Vercel Remote Cache

モノレポのCI高速化で最も効果が大きいのがリモートキャッシュの活用です。Turborepo v2では、Vercel Remote Cache以外にもAWS S3やGoogle Cloud Storageをバックエンドにしたself-hostedキャッシュサーバーが正式サポートになりました。

flowchart LR
    subgraph CI ["GitHub Actions CI"]
        A[push/PR] --> B[turbo run build test]
        B --> C{キャッシュHIT?}
    end
    C -- HIT --> D[スキップ\n即時完了]
    C -- MISS --> E[タスク実行]
    E --> F[キャッシュ書き込み]
    F --> G[(Remote Cache\nS3/GCS/Vercel)]
    D --- G
    G --> H[次回CI\nHIT率向上]

Self-hosted Cacheサーバーの設定例

[要確認] 「ducktape」というOSSキャッシュサーバー名およびghcr.io/vercel/turbo-cache-serverというイメージ名は、公式ドキュメントで正確な名称・URLをご確認ください。

Turborepo公式が提供するOSSキャッシュサーバーを使ったS3バックエンド構成:

# docker-compose.yml(社内キャッシュサーバー)
services:
  turbo-cache:
    image: ghcr.io/vercel/turbo-cache-server:latest
    environment:
      STORAGE_PROVIDER: s3
      S3_BUCKET: my-turbo-cache
      S3_REGION: ap-northeast-1
      TURBO_TOKEN: ${TURBO_TOKEN}
    ports:
      - '3000:3000'

Vercel vs Self-hosted コスト比較

[要確認] 以下の価格・SLA数値は執筆時点の参考値です。Vercelの料金プランは変更される場合があるため、公式サイトで最新情報をご確認ください。

項目Vercel Remote CacheSelf-hosted(S3)
月額費用(100GB)$20〜(Proプラン)約$2.3(S3標準)
セットアップ工数ほぼゼロ1〜2日
データ所在地Vercel管理自社管理
SLA99.99%自社責任
チームプラン人数制限ありなし

スタートアップや小規模チームはVercel、エンタープライズやコスト最適化を重視するチームはSelf-hostedが2026年現在の主流な選択です。


GitHub ActionsでのCI/CD最適化パイプライン

2026年現在のベストプラクティスは、affected packages検出matrixビルドの組み合わせです。変更のあったパッケージのみをビルド・テストすることでCIコストを大幅削減できます。

# .github/workflows/ci.yml
name: CI

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

env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ vars.TURBO_TEAM }}
  TURBO_REMOTE_ONLY: true

jobs:
  ci:
    name: Build & Test
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [22.x]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 差分検出のため全履歴取得

      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Lint
        run: pnpm turbo lint --filter='...[origin/main]'

      - name: Type Check
        run: pnpm turbo typecheck --filter='...[origin/main]'

      - name: Build
        run: pnpm turbo build --filter='...[origin/main]'

      - name: Test
        run: pnpm turbo test --filter='...[origin/main]'
        env:
          NODE_ENV: test

--filter='...[origin/main]'という記法がポイントで、mainブランチからの差分があるパッケージとその依存パッケージのみを対象にタスクを実行します。

CI実行時間の改善効果

[要確認] 以下の「18分→4分(約78%削減)」という数値は特定の導入事例に基づく参考値です。構成やパッケージ数によって効果は大きく異なります。

実際の導入事例では、20パッケージ構成のモノレポでCIの平均実行時間が18分→4分(約78%削減)という結果も出ています(2025年後半〜2026年にかけての導入報告より)。

pie title CI平均実行時間の内訳(改善後・20パッケージ構成)
    "キャッシュHIT(スキップ)" : 65
    "実際のビルド処理" : 20
    "テスト実行" : 10
    "セットアップ・インストール" : 5

2026年モノレポ運用のアンチパターンと対策

TurborepoとpnpmWorkspacesを導入しても、設定を誤ると逆効果になるケースがあります。よくある失敗パターンと対策を整理します。

アンチパターン一覧

アンチパターン症状対策
outputsの設定漏れキャッシュが効かないdist/**等を必ず明示
envの設定漏れ環境変数の変化を検知できずキャッシュ汚染が発生するenv: ['NODE_ENV', 'API_URL']等を列挙
persistent: trueタスクにdependsOnを設定devサーバー起動が無限待機になるdevタスクはdependsOnを削除
ルートのpackage.jsonに直接依存を追加Phantom Dependencyの温床になる必ず各パッケージのscoped名で管理
pnpm-lock.yaml.gitignoreに追加再現性のないインストールになる必ずコミットに含める

turbo.tsenv設定ミスを検出するスクリプト

// scripts/check-turbo-env.ts
// CI前にenv漏れを検出するユーティリティ
import { execSync } from 'child_process';

const result = execSync('turbo run build --dry-run=json').toString();
const dryRun = JSON.parse(result);

const missingEnv = dryRun.tasks.filter(
  (task: { hashOfExternalDependencies: string; envVars: string[] }) =>
    task.hashOfExternalDependencies === '' && task.envVars.length === 0
);

if (missingEnv.length > 0) {
  console.warn('⚠️  以下のタスクにenv設定がありません:', missingEnv.map((t: { taskId: string }) => t.taskId));
}

まとめ

2026年のモノレポ運用は、Turborepo 2.xとpnpm 9.xの組み合わせが事実上のスタンダードになりつつあります。本記事の要点を振り返ります。

  • Turborepo v2.3ではturbo.tsによるTypeScript設定とフルRust実装が採用され、設定の型安全性とパフォーマンスが大きく向上した
  • pnpm 9.x Catalog機能を活用することで、全パッケージの依存バージョンをpnpm-workspace.yaml一か所で一元管理でき、バージョン不整合のトラブルを排除できる
  • リモートキャッシュはVercel Remote CacheとSelf-hosted(S3)の2択。小規模チームはVercel、コスト・セキュリティ重視のチームはSelf-hostedを選択する
  • --filter='...[origin/main]' による差分ビルドをCIに組み込むことで、実行時間を最大80%削減できる
  • outputsenvの設定漏れがキャッシュ汚染の主因。CIでの事前チェックスクリプトの導入が有効

次のアクション: まずpnpm-workspace.yamlにCatalogを追加してバージョン管理を集約し、続いてturbo.tsへ移行してTypeScriptの型チェックを活用してみてください。リモートキャッシュはVercel無料枠から始めて、CIの高速化を体験するところからスタートするのがおすすめです。

関連記事