Monorepo は『複数プロジェクトの開発体験を一段上げる』
マイクロサービスやマルチパッケージ開発で Monorepo (単一リポジトリ管理) が広く採用されています。本記事では編集部の視点で、設計と運用のポイントを公開情報をもとに整理します。マイクロサービス設計 もご参考に。
主要ツールの特徴
(1) pnpm workspaces:シンプル・低オーバーヘッド・速い。(2) Turborepo:リモートキャッシュ・タスクパイプライン。(3) Nx:強力な依存グラフ・コード生成・プラグインエコシステム。(4) Lerna:歴史的選択肢。現在は別管理者下で継続。(5) Yarn Berry workspaces:Yarn 派の選択。判断軸:小規模なら pnpm、ビルド時間が長いなら Turborepo、複雑なら Nx。
ディレクトリ構造
(1) apps/:デプロイ可能なアプリ。(2) packages/:共通ライブラリ。(3) tools/:開発ツール・スクリプト。(4) docs/:ドキュメント。(5) config/:ESLint/Prettier/tsconfig の共通設定。依存方向は apps → packages のみに統一すると保守性が大きく上がります。
ビルド最適化
(1) 依存グラフベースの差分実行:変更された箇所のみ再ビルド。(2) リモートキャッシュ:チーム/CI で共有。(3) 並列実行:CPU コア活用。(4) タスクパイプライン:build → test → lint の順序定義。(5) キャッシュキーの工夫:ソース+依存+設定で確実な無効化。Observability 実践 でビルド時間計測も。
CI/CD の設計
(1) 変更パッケージのみテスト:affected を活用。(2) 並列ジョブ:matrix で並行実行。(3) キャッシュ共有:S3/Vercel Remote Cache。(4) デプロイ独立:パッケージ単位で個別デプロイ。(5) バージョニング:Changesets で自動リリース。
運用で効くテクニック
(1) 依存ロックの統一:Workspace 全体で1 lockfile。(2) TypeScript Project References:型解決を高速化。(3) 共通の Code Owners:自動レビュー割当。(4) パッケージ間のバージョン整合:syncpack で監視。(5) 不要なパッケージの削除:依存グラフ可視化で発見。
失敗しがちなパターン
(1) 循環依存:パッケージ間で双方向参照。(2) 巨大な共通パッケージ:何でも入れて変更頻度が上がる。(3) ビルドキャッシュなし:CI が長時間化。(4) Polyrepo に戻したくなる:境界設計の失敗。(5) ローカルでビルドが終わらない:差分実行未対応。対策は、(1)依存方向統一、(2)共通パッケージ分割、(3)Turborepo/Nx 導入、(4)境界設計を週次見直し、(5)affected コマンド活用、です。