lerna、nx、turbo はすべて JavaScript/TypeScript プロジェクトにおけるモノレポ(monorepo)ワークフローを支援するツールです。これらはパッケージ間の依存関係管理、タスク実行、ビルド最適化などの課題に対処しますが、設計思想や機能範囲、パフォーマンス特性に大きな違いがあります。lerna は歴史的に最も古く、主に npm パッケージのバージョニングと公開に焦点を当てています。nx はフルスタックな開発環境を提供し、コード生成、依存関係可視化、高度なキャッシュ戦略を備えています。一方、turbo(Turborepo)は高速なインクリメンタルビルドとリモートキャッシュに特化した軽量なタスクランナーとして設計されています。
JavaScript/TypeScript のモノレポ管理には、lerna、nx、turbo(Turborepo)という3つの主要な選択肢があります。これらは「複数のパッケージを1つのリポジトリで管理する」という共通の目標を持ちますが、アプローチと機能範囲は大きく異なります。この記事では、実際の開発シナリオに基づいて、各ツールの強み・弱みを深く掘り下げます。
lerna は、もともと npm パッケージのバージョニングと公開を目的として開発されました。lerna version と lerna publish コマンドにより、変更のあったパッケージだけを自動的にバージョンアップし、npm に公開できます。
// lerna.json
{
"version": "independent",
"packages": ["packages/*"]
}
# 変更のあったパッケージだけをバージョンアップ
lerna version --conventional-commits
# 公開
lerna publish from-git
nx にも nx release コマンド(v18以降)が追加されましたが、従来はバージョニング機能が弱く、多くのチームが Lerna と併用していました。現在は Nx 単体でも可能ですが、Lerna ほどの成熟度はありません。
# Nx のリリース機能(ベータ段階)
nx release version
nx release publish
turbo は、バージョニングや公開機能を一切提供しません。これは意図的な設計で、Turborepo は「タスクランナー」に特化しており、パッケージ公開は別ツール(例: Changesets、Lerna)に任せる想定です。
💡 ポイント:npm パッケージを頻繁に公開するライブラリ中心のモノレポでは、
lernaが依然として有力な選択肢です。一方、アプリケーション中心のモノレポ(例: 複数のフロントエンド + バックエンド)では、バージョニング機能は不要なことが多く、nxやturboの方が適しています。
lerna のタスク実行(例: lerna run build)は、パッケージ間の依存関係を考慮して順序を決定しますが、キャッシュ機能がありません。毎回フルビルドになるため、大規模なモノレポでは時間がかかります。
# lerna は依存関係順にビルドするが、キャッシュなし
lerna run build --scope=app-web
nx は、ローカルおよびリモートの高度なキャッシュ機構を備えています。タスクの入力(ソースコード、依存関係、環境変数など)に基づいてハッシュを計算し、同じ入力であれば結果を再利用します。さらに、affected コマンドで変更の影響を受けたプロジェクトだけを実行できます。
# 影響を受けたプロジェクトだけをビルド
nx affected:build
# キャッシュヒット時は「retrieved from cache」と表示
// nx.json
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test", "lint"]
}
}
}
}
turbo も同様に、インクリメンタルなキャッシュを提供しますが、設定が極めてシンプルです。turbo.json でパイプラインを定義するだけで、依存関係に基づく並列実行とキャッシュが有効になります。
// turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"],
"inputs": ["src/**", "test/**"]
}
}
}
# turbo は自動でキャッシュを活用
turbo run build
💡 ポイント:
nxとturboはどちらもキャッシュで高速化しますが、nxはより詳細な制御(例: キャッシュの無効化条件、カスタムハッシュアルゴリズム)が可能で、turboは「設定不要」の哲学でシンプルさを重視しています。
lerna は、packages/ 配下の各ディレクトリを独立した npm パッケージとして扱います。依存関係は package.json の dependencies で管理され、lerna bootstrap でシンボリックリンクを作成します(ただし、最近の Lerna は Yarn/PNPM のワークスペース機能を推奨しており、bootstrap は非推奨)。
// packages/app/package.json
{
"name": "@myorg/app",
"dependencies": {
"@myorg/ui": "*"
}
}
nx は、ワークスペース内に「プロジェクト」としてアプリやライブラリを定義します。project.json(または package.json)で各プロジェクトのメタデータを管理し、nx graph コマンドで依存関係を可視化できます。
// apps/web/project.json
{
"name": "web",
"targets": {
"build": {
"executor": "@nx/next:build",
"outputs": ["{options.outputPath}"]
}
}
}
# 依存関係グラフをブラウザで表示
nx graph
turbo は、Yarn/PNPM/NPM のネイティブなワークスペース機能に完全に依存します。package.json の workspaces フィールドでパッケージを定義し、Turborepo 自体はワークスペース構造を認識しません。
// package.json (root)
{
"workspaces": ["apps/*", "packages/*"]
}
💡 ポイント:
nxは独自のプロジェクトメタデータを持ち、高度な分析が可能ですが、turboは既存のパッケージマネージャーの仕組みをそのまま使うため、移行コストが低いです。
lerna は、最小限の機能に絞られており、コード生成や高度なLintルールなどは提供しません。他のツール(例: ESLint、Prettier)との統合は手動で行う必要があります。
nx は、コード生成(Schematics) や コンテキスト感知Lint(例: 使用していない依存関係の検出)など、豊富なDX機能を提供します。また、React、Angular、Node.js など多数のフレームワーク向けの公式プラグインがあります。
# Nx で React コンポーネントを生成
nx g @nx/react:component button --project=ui
turbo は、Vercel 社が開発しており、Next.js、Remix、SvelteKit などと緊密に統合されています。例えば、Next.js プロジェクトでは turbo run dev で高速な開発サーバーが起動します。
// turbo.json for Next.js
{
"pipeline": {
"dev": {
"persistent": true,
"cache": false
}
}
}
# 高速な並列開発サーバー
turbo run dev
💡 ポイント:Vercel エコシステム(特に Next.js)を使っているなら、
turboは最小限の設定で最大の恩恵を受けられます。一方、多様な技術スタックを管理する大規模チームでは、nxの包括的な機能セットが有利です。
lerna は、リモートキャッシュ機能を提供していません。CI上での高速化は、自前でキャッシュを実装する必要があります。
nx は、Nx Cloud(商用サービス)またはセルフホスト可能な分散キャッシュをサポートしています。CI上でビルド結果を共有し、チーム全体でキャッシュを再利用できます。
# Nx Cloud に接続
nx connect-to-nx-cloud
turbo も、Vercel Remote Caching を無料で提供しています。turbo token を設定するだけで、CIやローカル間でキャッシュを共有できます。
# Vercel Remote Cache を有効化
echo "TURBO_TOKEN=your_token" >> .env.local
💡 ポイント:リモートキャッシュは
nxとturboの共通の強みですが、turboの方が設定が簡単で、無料で利用できます。nxの Nx Cloud はより詳細な分析ダッシュボードを提供します。
| 特徴 | lerna | nx | turbo |
|---|---|---|---|
| 主な用途 | npm パッケージのバージョニングと公開 | 大規模モノレポの包括的管理 | タスク実行の高速化とキャッシュ |
| キャッシュ | ❌ | ✅(ローカル + リモート) | ✅(ローカル + リモート) |
| 影響範囲分析 | ❌ | ✅(nx affected) | ✅(--filter オプション) |
| コード生成 | ❌ | ✅ | ❌ |
| 依存関係可視化 | ❌ | ✅(nx graph) | ❌ |
| 設定の複雑さ | 低 | 高 | 低 |
| Vercel/Next.js 統合 | ❌ | △(プラグインあり) | ✅(ネイティブ) |
lerna(ただし、Changesets との併用も検討)nxturbo現代のモノレポでは、lerna 単体ではなく、turbo + changesets や nx + lerna といった組み合わせも一般的です。プロジェクトの規模、チームのスキルセット、使用技術スタックを考慮して、最適なツールを選んでください。
turbo は、既存のビルドシステム(例: Vite、Next.js、esbuild)をそのまま使いつつ、タスク実行の高速化とキャッシュを追加したい場合に最適です。設定が非常にシンプルで、JSON ベースのパイプライン定義だけで高速な並列実行とインクリメンタルビルドを実現できます。特に、Next.js や Remix など Turborepo と緊密に統合されたフレームワークを使用しているプロジェクトでは、最小限の設定で最大の効果が得られます。
nx は、大規模チームや複雑なアプリケーション(React、Angular、Node.js など)を含むモノレポで、包括的な開発体験(DX)とパフォーマンス最適化を求める場合に最適です。依存関係グラフの可視化、影響を受けるプロジェクトの特定、リモートキャッシュ、コード生成(schematics)など、高度な機能を活用したいなら Nx を選ぶべきです。ただし、学習コストがやや高く、設定が複雑になる可能性があります。
lerna は、複数の独立した npm パッケージを含むシンプルなモノレポで、特にパッケージのバージョン管理と npm publish の自動化が必要な場合に適しています。ただし、ビルドやテストの高速化、依存関係に基づくタスク実行といった高度なワークフロー最適化には向いていません。新しいプロジェクトでは、Lerna のコア機能(例: version と publish)のみを必要とする場合に限定して検討すべきです。
Turborepo is the build system for coding agents.
Visit https://turborepo.dev to get started with Turborepo.
See CONTRIBUTING.md for more information.
The Turborepo community can be found on GitHub Discussions, where you can ask questions, voice ideas, and share your projects.
To chat with other community members, you can join Vercel Community's #turborepo tag.
Our Code of Conduct applies to all Turborepo community channels.
Turborepo is used by the world's leading companies. Check out the Turborepo Showcase to learn more.
Follow @turborepo on X for project updates.
If you believe you have found a security vulnerability in Turborepo, we encourage you to responsibly disclose this and not open a public issue. We will investigate all legitimate reports. Email security@vercel.com to disclose any security vulnerabilities.