Monorepoとは何か
npmで管理する複数のpackageを、まとめて一つのgitリポジトリで管理すること。
具体的に
例えば、 npm上にBabelは108以上のパッケージがある。
babelはpluginを追加していくスタイルなので、
babel-core, babel-cli, babel-preset-es2017, babel-preset-flow ....
と、たくさんのパッケージがあり npm install babel-preset-flow
等々して取り込んでいく。
従来、npmでは「1リポジトリ=1パッケージ」が標準だったが、多数パッケージを管理するBabelのようなプロジェクトでは多数リポジトリを扱うことになり、混乱が大きい。
そこで、単一リポジトリの /packages
以下にたくさんパッケージを作り(フォルダとpackage.jsonを多数作り)、管理するのがMonorepo。
これ以上は 実際のBabelのpackagesディレクトリ を見たほうが早い。
単一リポジトリの中に多数のパッケージがあるのがわかると思う。
使用しているプロジェクト
Babel, React, Meteor, そして Ember などが採用。
基本的には多数パッケージを扱う巨大フレームワークが採用しているわけですね。
何が利点か
利点:
- 統一された lint, build, test, release プロセス。
- モジュールを横断した変更が容易。
- issueを上げる場所がひとつ(のため見落としがすくない)
- 開発環境を立ち上げるのが簡単。(100のリポジトリで、個別に100個の開発環境を整備するために100回
npm install
と考えるだけで・・Oops) - モジュールを横断するテストを走らせるのが容易で、それはつまり複数モジュール環境で起きるバグを見つけやすくなる。
欠点:
- コードが必要以上に威圧的になっちゃう
- gitリポジトリが肥大化
- npmの検索結果で低く表示される。(npmはテストのコードカバレッジを計測しているが、monorepoは個別パッケージでテストしてないのでカバレッジが低くなるため)
僕も/私も使うべきか
規模によっては使用することも考えて良い。
SPAで、フロント・サーバサイド・両者共通機能パッケージ(model関連など)幾つか…と3-10個程度のが存在するときに、
両者共通機能パッケージをmonorepoとし、例えばサーバサイドに寄生させてもいいかもしれない。
ただし、十分に小さく独立性があまりない機能セットの場合、無意味なパッケージ分割は単に混乱を生むだけである。どういう単位で分割するのが良いかはアーキテクチャ・設計なのでよく考えよう。