採用してるプロジェクトをいくつか調べたりしたまとめ。
実運用に入る前の調査で、推測もあるので大目に見てほしい。
個人的なまとめ
- 今やろうとしてること的には yarn workspace だけでいいかも
- npm に公開したくなっても後から lerna 導入はできそう
- lerna 以外はなんとも
monorepo とは
monorepo 自体の良し悪しはググればそこそこ出てくる。
babel の monorepo 1 つ 1 つを GitHub のリポジトリに切り出した地獄を想像すれば Pros はだいたい理解できる。
ざっと調べる限り monorepo 自体の考え方は、単に一つのレポジトリに複数のモジュールが突っ込まれているだけなので難しくなさそう。
共通ライブラリを作りたいならそのライブラリの設計のほうが、コード分割でアップデートし難さを解消したいならその分割単位を考えるほうが、よほど難しいはず。
問題を monorepo で解消できるならやればよい、って感じだろう。
yarn を使って monorepo
yarn には workspaces という機能があり monorepo をサクッと実現できる。
実際に作ってみた monorepo が こちら 。 root の package.json に下記を記入するだけで、とくに変わったことはしていない。
"private": true,
"workspaces": ["packages/*"],
また、 packages 以下の myrepo-shared, myrepo-awesome それぞれに package.json が書かれていて、両方の dependencies に lodash が書かれている。
これを clone して yarn
を実行すると、下記のようなディレクトリ構成になる。
.
├── node_modules
│ ├── lodash
│ ├── myrepo-awesome -> ../packages/myrepo-awesome
│ └── myrepo-shared -> ../packages/myrepo-shared
├── package.json
├── packages
│ ├── myrepo-awesome
│ │ ├── index.js
│ │ └── package.json
│ └── myrepo-shared
│ ├── package.json
│ └── str-or-num.js
└── yarn.lock
各 packages 以下には node_modules ができておらず root にパッケージがインストールされる。さらに各 packages への symlink ができる。
node.js の仕様上、 node_modules はディレクトリを遡って解決されるので、この状態で cd packages/myrepo-awesome
とかに移動して node index.js
を実行しても、ルートディレクトリで node packages/myrepo-awesome/index.js
を実行しても、ちゃんと依存を解決できる。
なお React はこれで monorepo 運用している模様。 lerna も lerna.json で "npmClient": "yarn", "useWorkspaces": true
とするとこれを使うようになる (PR はこちら) 。
lerna の使い所
上記の通り yarn workspace で単純な monorepo を作って共通モジュールを作ったりはできる。
なら lerna は何に使うのか?
公式は主要コマンドとして bootstrap と publish を挙げていて、このうち bootstrap は yarn workspace がやっている話なので、 publish がメインの用途となりそう。
各ディレクトリで run scripts を実行したい場合に lerna run
が使える。
TBD
lerna 以外の選択肢
こういうのすら乱立するのが JS の多様性。
安心と信頼の lerna で良さそう。困ったら検討するかも?
npm について
npm には yarn workspace に相当する機能はないので monorepo をやりたいなら現状は yarn を入れたほうが快適で安全っぽい。
yarn workspace についてのブログ記事 でも package ごとに yarn install するのでディスクが無駄になるとか、あとで lerna が張った symlink による dependencies の矛盾に yarn が気づけないとか、そういうのを解消するために yarn workspace を作ったと書いてある。
とはいえ lerna 自体が長いこと npm 対応し続けてるプロジェクトなので使えないってことはないんじゃないかと思われる。
yarn は brew upgrade で node.js を壊すことがあるので(あるよね?)、個人的には npm 側にこの実装がほしい……。