toshi-toma blog

主にフロントエンド、作業ログあとは色々なメモ ✍️ 🍅

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

基本的にできることは同じ。 以下の記事がよくまとまってる。

blog.cybozu.io

その他、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_modulesyarn.lockで管理する。バージョンが違うようなときはパッケージごとにnode_moculesが作られることもある。

パッケージごとに、特定のパッケージをインストールする場合

いくつかの方法がある

パッケージ全体で利用する、共通パッケージをインストールする場合

トップレベルで、yarn add -W <package>

rootでyarn addするとエラーがでるのでWオプションをつける

yarn add | Yarn

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を使って効率的にビルドできる

publish

lerna publishがあり、-conventional-commits オプションを利用することで commit log からバージョンを決定でき、CHANGELOG.mdも自動作成できる。

参考