Monorepoについて調べた 〜Lerna & Yarn Workspaces〜
Monorepoについて
OSSや企業での開発でMonorepoを採用しているケースをたまに目にします。これまで、Monorepoでの開発に参加したことがないので、調べてみました。
Monorepoは、単一のリポジトリで複数のパッケージを管理すること。BabelやJest, ReactなどなどいろんなOSSが採用している。(mono=単一という意味)
実現方法としては、LernaとYarn Workspacesを使う方法が多い。できることは両者ほぼ同じで、個別でだいたいやりたいことはできるけど、両方使うパターンも多いっぽい。
いいところ
- 複数のパッケージをまたいだ機能追加やバグ修正でも、1つのPRで完結する
- 相互に依存しているパッケージ同士の連携が容易
- 別れていると、publishしたり、npm linkすることになるので
- 依存しているパッケージの管理が楽
- 全体をまとめて、一緒にテストできる
あたりがいいところ。
LernaとYarn Workspaces
基本的にできることは同じ。 以下の記事がよくまとまってる。
その他、Lernaについて
バージョンのFixedとindependent
LernaにはFixed(すべてのパッケージが同じバージョン)とIndependent(パッケージごとに異なるバージョン)のモードがある
lernaでのmonorepoにおけるリリースフロー(Fixed/Independent) | Web Scratch
lerna-changelog
lerna-changelogというlerna公式ツールがある。これは、ラベルを付与したPR単位でリリースノートを作成してくれるツール。
lerna-changelogで始める頑張りすぎないリリースノート自動生成 | WEB EGG
Lerna and Yarn Workspaces
LernaとYarnを一緒に使うパターンが多い
最初の設定
- package.jsonのworkspaceフィールドを定義
- トップレベルはprivateフィールドをtrue
- lerna.jsonで"npmClient": "yarn"する
- lerna initやlerna createでパッケージ作成
パッケージのインストール
全パッケージの依存パッケージをインストール
トップレベルでyarn install
叩けば良い。基本的にはトップレベルのnode_modules
やyarn.lock
で管理する。バージョンが違うようなときはパッケージごとにnode_mocules
が作られることもある。
パッケージごとに、特定のパッケージをインストールする場合
いくつかの方法がある
- 対象のパッケージで普通に
yarn add
する yarn workspace <workspace_name> add <package>
lerna add <package> —scope <project>
パッケージ全体で利用する、共通パッケージをインストールする場合
トップレベルで、yarn add -W <package>
rootでyarn addするとエラーがでるのでWオプションをつける
npm-scripts
トップレベルで、各パッケージで定義されているnpm-scriptsを一括実行できる。
yarn workspaces run test
lerna run test
- -streamでログが見れる
別パッケージの参照
@toshi-toma/ui
パッケージで、@toshi-toma/types
を参照するようなケースで、それらをMonorepoで管理してると便利みたいな話。
Monorepoで管理してる場合、トップレベルのnode_modulesを見ると、packages/
で管理してるパッケージを持っている。
実態は、packages/
の各パッケージへのシンボリックリンク。なのでrequireやimportは何も気にせずにできる。ただし、依存してるなら、package.jsonのdependenciesには明記する。lerna runを走らせたとき、package.jsonを見て、プロジェクト内に依存があれば、先にそっちを実行してくれるとかがある。
TypeScript
packages/
直下にtsconfig.base.json的なのを作って、各プロジェクトのtsconfig.json
では、Baseのファイルをextendsすると便利- TSのパッケージ間で依存関係が生まれてきたら、Project Referencesを使って効率的にビルドできる
- 各パッケージの
tsconfig.json
のreferencesで依存してるパッケージを明記すれば、依存してるプロジェクトをビルドできる(tsc --build) - packages直下のtsconfigに全パッケージのreferencesを記述すれば、
tsc -b
で全プロジェクトをビルドできる - 各パッケージの
tsconfig.json
でcompositeをtrueにする必要あり - 参考: https://efcl.info/2020/11/23/workspaces-to-typescript-project-references/
- 各パッケージの
publish
lerna publish
があり、-conventional-commits オプションを利用することで commit log からバージョンを決定でき、CHANGELOG.mdも自動作成できる。