Turborepo Monorepo ガイド: マルチアプリ プロジェクトの管理
複数のアプリケーションと共有パッケージを含む Monorepos は、現在、相互接続されたソフトウェア製品を構築する企業の標準アーキテクチャとなっています。 Vercel が買収した Turborepo は、タスクの依存関係の処理、キャッシュ、数十のパッケージにわたる並列実行など、monorepos を実用的なものにするビルド オーケストレーション レイヤーを提供します。
重要なポイント
- Turborepo リモート キャッシュにより、増分変更の CI ビルド時間を 80 ~ 90% 削減できます
- タスク パイプラインにより、パッケージが正しい依存関係の順序で自動的にビルドされるようになります
- 共有パッケージ (タイプ、バリデーター、ユーティリティ) により、アプリ間でのコードの重複が排除されます。
- pnpm ワークスペースは、モノリポジトリのディスク効率の高い依存関係管理を提供します
モノレポのアーキテクチャ
ディレクトリ構造
一般的な Turborepo モノリポでは、アプリケーションを共有パッケージから分離します。
my-monorepo/
apps/
api/ # NestJS backend
web/ # Next.js frontend
docs/ # Documentation site
mobile/ # React Native app
packages/
db/ # Drizzle ORM schemas and migrations
types/ # Shared TypeScript types
validators/ # Zod validation schemas
utils/ # Shared utility functions
ui/ # Shared UI components
config/ # Shared configuration (ESLint, TypeScript)
turbo.json # Turborepo configuration
pnpm-workspace.yaml
package.json # Root package.json
ワークスペースの構成
pnpm-workspace.yaml でワークスペースを定義します。
packages:
- "apps/*"
- "packages/*"
各ワークスペースには、依存関係とスクリプトを含む独自の package.json があります。共有パッケージは、ワークスペース プロトコルを使用して参照されます。
{
"dependencies": {
"@myorg/types": "workspace:*",
"@myorg/validators": "workspace:*",
"@myorg/utils": "workspace:*"
}
}
Turborepo 構成
タスクパイプライン
turbo.json は、タスクが相互にどのように関連するかを定義します。
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"dev": {
"dependsOn": ["^build"],
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["build"]
}
}
}
重要な概念:
- dependsOn: ["^build"]: キャレット (^) は、「最初にすべての依存関係を構築する」ことを意味します。 Web アプリを構築するとき、Turborepo は最初にパッケージ/タイプ、パッケージ/バリデータ、およびパッケージ/ユーティリティを構築します。
- 出力: Turborepo がキャッシュするファイル。以降の実行では、入力が変更されていない場合、Turborepo は再構築する代わりにキャッシュされた出力を再生します。
- persistent: true: 実行を続ける開発サーバーの場合。
- キャッシュ: false: 常に実行する必要があるタスク (開発サーバーなど) のキャッシュを無効にします。
共有パッケージ
タイプパッケージ
アプリ全体で使用される TypeScript タイプを一元化します。
// packages/types/src/user.ts
export interface User {
id: string;
email: string;
name: string;
role: "admin" | "user" | "support";
createdAt: Date;
}
export type CreateUserDTO = Omit<User, "id" | "createdAt">;
export type UpdateUserDTO = Partial<CreateUserDTO>;
バリデーターパッケージ
フロントエンドとバックエンド間で共有される Zod スキーマ:
// packages/validators/src/user.ts
import { z } from "zod";
export const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(255),
role: z.enum(["admin", "user", "support"]),
});
ビルド構成
共有パッケージは、アプリが使用する前に事前に構築する必要があります。 TypeScript を JavaScript にコンパイルするビルド スクリプトを使用して各パッケージを構成します。
{
"scripts": {
"build": "tsc --project tsconfig.json",
"dev": "tsc --watch"
}
}
キャッシュ戦略
ローカルキャッシュ
Turborepo は、デフォルトでタスクの出力を node_modules/.cache/turbo にキャッシュします。ターボ ビルドを実行しても何も変更されない場合、Turborepo はキャッシュされた出力をミリ秒単位で再生します。
リモート キャッシング
For CI/CD, enable remote caching to share build artifacts across team members and CI runs:
npx turbo login
npx turbo link
リモート キャッシュとは、1 台の開発者マシン上で完了したビルドまたは CI の実行を誰でも利用できることを意味します。その影響は劇的で、増分 CI ビルドは 10 分から 1 分未満に短縮されます。
開発ワークフロー
すべてのアプリを実行する
pnpm dev # Starts all apps and watches all packages
Turborepo は最初に共有パッケージをビルドし (dev は ^build に依存するため)、次にアプリ開発サーバーを並行して起動します。共有パッケージに変更を加えると、再構築がトリガーされ、それが使用するアプリに伝播されます。
特定のアプリの実行
pnpm dev --filter=web # Only the web app and its dependencies
pnpm dev --filter=api # Only the API and its dependencies
すべてを開始する必要がない大規模なモノリポジトリでは、フィルタリングが不可欠です。
CI/CD の最適化
影響を受けるパッケージの検出
Turborepo は、最後のコミット以降にどのパッケージが変更されたかを判断し、影響を受けるパッケージのタスクのみを実行します。
turbo build --filter=...[HEAD^1]
これにより、最新のコミットで変更されたパッケージとその依存パッケージに対してのみビルドが実行されます。
並列実行
Turborepo は独立したタスクを並行して実行します。パッケージ/タイプとパッケージ/ユーティリティに依存関係がない場合、それらは同時にビルドされます。同時実行レベルは、使用可能な CPU コアに適応します。
よくある質問
Q: Turborepo monorepo はいくつのパッケージを処理できますか?
Turborepo は、数百のパッケージを含むモノリポジトリを処理します。タスク グラフが起動時に分析され、キャッシュによりほとんどのパッケージが増分変更のビルドをスキップするため、パフォーマンスは適切に拡張されます。
Q: ワークスペースには pnpm または npm を使用する必要がありますか?
モノリポジトリには pnpm を強く推奨します。コンテンツ アドレス指定可能なストアにより、パッケージ間の依存関係が重複排除され、ディスク容量とインストール時間が大幅に節約されます。 pnpm ワークスペースは、依存関係の解決に関してもより厳密であり、欠落している依存関係の宣言を検出します。
Q: アプリ間で異なる Node.js バージョンをどのように処理すればよいですか?
各 package.json のエンジン フィールドを使用して、Node.js のバージョン要件を指定します。ランタイムの違いについては、アプリごとに適切なバージョンを使用するように CI を構成します。
Q: Turborepo を段階的に導入できますか?
はい。 turbo.json を既存の pnpm ワークスペース プロジェクトに追加し、タスク パイプラインを構成します。既存のスクリプトは引き続き機能します。再構築することなく、キャッシュとタスク オーケストレーションをすぐに利用できるようになります。
次は何ですか
Turborepo は、モノリポ開発をメンテナンスの負担から生産性の向上に変えます。シンプルな構造から始めて、プロジェクトの要求に応じて拡張してください。
モノレポ アーキテクチャのコンサルティングについては ECOSIRE にお問い合わせ、マルチアプリ ERP アーキテクチャについては Odoo 統合サービス をご覧ください。
ECOSIRE が発行 -- エンタープライズ ソフトウェア ソリューションによるビジネスの拡大を支援します。
執筆者
ECOSIRE Research and Development Team
ECOSIREでエンタープライズグレードのデジタル製品を開発。Odoo統合、eコマース自動化、AI搭載ビジネスソリューションに関するインサイトを共有しています。
関連記事
Docker Odoo デプロイメント: 本番環境に対応したコンテナーのセットアップ
Odoo を実稼働用の Docker コンテナにデプロイします。 Docker Compose 構成、PostgreSQL セットアップ、Nginx リバース プロキシ、SSL、バックアップ、スケーリングをカバーする完全なガイド。
Drizzle ORM と NestJS を使用した API の構築: 完全ガイド
Drizzle ORM と NestJS を使用してタイプセーフな API を構築します。実稼働アプリケーションのスキーマ定義、移行、クエリ構築、関係、トランザクション、およびテスト パターンについて学びます。
Playwright テスト ガイド: Next.js アプリケーションの E2E テスト
Playwright を使用して、Next.js アプリケーションの信頼できるエンドツーエンドのテストを作成します。セットアップ、ページ オブジェクト、認証テスト、ビジュアル リグレッション、CI/CD 統合をカバーする完全なガイド。