Skip to content

Use npm Workspaces for Monorepo Management

複数の関連プロジェクトを統一管理するためのmonorepo戦略が必要である。従来、単一のリポジトリで複数のパッケージを管理する場合、依存関係の管理、ビルド順序の制御、バージョン管理などが煩雑になる課題があった。

現在のプロジェクト構成では、以下の要件を満たすmonorepo管理ツールが必要である。

  • 共通ライブラリとアプリケーションの同時開発
  • パッケージ間の依存関係の一元管理(重複インストールの回避)
  • 開発環境のセットアップの簡素化
  • CI/CDパイプラインでの並列ビルド・テスト実行
  • ツールベンダーへの過度な依存を避けること

monorepo管理にnpm workspacesを採用する。Node.jsエコシステムの標準機能を活用することで、サードパーティツールへのロックインを避け、シンプルで安定した開発体験を提供する。

  • 利点:

    • Node.jsエコシステムの標準機能(ベンダーロックインなし)
    • 追加のツールインストールが不要
    • シンプルな設定(package.jsonのみ)
    • npmの標準コマンドで操作可能
    • 依存関係の重複解決(hoisting)が自動
    • CI/CDでの設定が簡単
    • 学習コストが低い
  • 欠点:

    • 高度な機能(キャッシュ、タスクランナー等)は別途実装が必要
    • ビルド最適化機能が限定的
    • 大規模monorepoでのパフォーマンス制約
    • タスクの並列実行制御が基本的
  • 利点:

    • 高速なビルドキャッシュシステム
    • インクリメンタルビルド対応
    • タスクの並列実行最適化
    • 優れたDX(Developer Experience)
  • 欠点:

    • Vercel社への依存(ベンダーロックイン)
    • 設定の複雑性
    • 新しいツールのため長期安定性が未知数
    • 追加の学習コストと設定管理
  • 利点:

    • 豊富な機能セット(ジェネレーター、キャッシュ等)
    • 大規模プロジェクト向けの最適化
    • 多言語サポート
    • 成熟したエコシステム
  • 欠点:

    • 複雑な設定と学習コストが高い
    • Nx社への依存
    • オーバーエンジニアリングになりやすい
    • 小規模プロジェクトには過剰
  • 利点:

    • 長い開発履歴と安定性
    • バージョン管理機能が充実
    • 豊富なドキュメントとコミュニティ
  • 欠点:

    • メンテナンスが停滞している
    • 現代的なworkspace機能が不足
    • パフォーマンスが劣る
    • 新機能の追加が期待できない

この決定による影響を記述する。

  • ポジティブな影響:

    • ベンダーロックインを回避し、長期的な安定性を確保
    • セットアップと運用が簡単で、チーム全体の習得が容易
    • npmエコシステムの標準に従うことで、互換性問題が少ない
    • CI/CDパイプラインの設定が簡素化される
    • 依存関係の管理が透明で予測可能
  • ネガティブな影響:

    • 大規模プロジェクトでのビルド最適化が限定的
    • 高度な機能は追加実装が必要
    • キャッシュ機能が基本的
  • リスク:

    • プロジェクト規模拡大時にパフォーマンス問題が発生する可能性
    • 複雑なタスク依存関係の管理が困難になる場合がある
    • 他のツールと比較して機能的制約がある
{
"name": "project-root",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"scripts": {
"build": "npm run build --workspaces",
"test": "npm run test --workspaces",
"lint": "npm run lint --workspaces",
"dev": "npm run dev --workspace=web"
},
"devDependencies": {
"@company/eslint-config": "*",
"typescript": "^5.0.0"
}
}
project-root/
├── package.json
├── apps/
│ ├── web/
│ │ └── package.json
│ └── mobile/
│ └── package.json
├── packages/
│ ├── ui-components/
│ │ └── package.json
│ ├── shared-utils/
│ │ └── package.json
│ └── types/
│ └── package.json
└── tools/
└── build-config/
└── package.json
apps/web/package.json
{
"name": "@company/web",
"dependencies": {
"@company/ui-components": "*",
"@company/shared-utils": "*"
}
}
Terminal window
# 特定のworkspaceでコマンド実行
npm run build --workspace=web
# 全workspaceでコマンド実行
npm run test --workspaces
# workspaceにパッケージを追加
npm install lodash --workspace=apps/web
# workspace間の依存関係を追加
npm install @company/ui-components --workspace=apps/web
# GitHub Actions例
- name: Install dependencies
run: npm ci
- name: Build all packages
run: npm run build --workspaces
- name: Test changed packages
run: npm run test --workspaces --if-present