モノリシックな大規模ライブラリ開発
参考
概要
モノリシックレポジトリ(モノレポ)とは
Lernaとyarn workspace
結局何が解決できるのか
注意すべき点
まとめ
所感と作りたいもの
モノリシックレポジトリ(モノレポ)とは
こんなレポジトリ!
特徴
packagesというディレクトリがある!
root dirに 共通のpackage.jsonがある!
packages/hogePackage/package.json がある!
一番トップレベルで共通ライブラリを使用し、他の場所でも他の依存パッケージが存在している。
packages配下のものがnpmなどにpublishされる!
lerna と yarn workspace
lernaとは
複数 npm パッケージを単一リポジトリで一元管理
lerna bootstrap コマンドを使った Monorepo すべての依存パッケージを一括インストール
重複した依存パッケージの hoisting(巻き上げ)
hoisting とは、パッケージ間で重複している依存パッケージをそれぞれ別にインストールするのではなく、親となるディレクトリにインストールして共有することです
nishiyamayudai.icon hoist は綱引きの時の掛け声「オーエス(Oh Hisse!)」の元となったフランス語 hisser「(綱を)引く、引き揚げる」と同語源らしいです
lerna publish コマンドを使った、変更があるパッケージの一括 npm publish
すべての npm パッケージのバージョンを同一にするか、個別に管理するか(independent mode)を選択可能
lerna run コマンドを使った Monorepo で管理しているパッケージが持っている npm-scripts の一括実行
既存の git リポジトリから Monorepo へのインポート
yarn workspaceとは yarn v1系を想定して話してます
複数 npm パッケージを単一リポジトリで一元管理
yarn install コマンドを使った Monorepo すべての依存パッケージを一括インストール
依存パッケージの hoisting
yarn workspaces コマンドを使った Monorepo で管理しているパッケージが持っている npm-scripts の一括実行
単一のyarn.lockファイルですべての依存関係を管理
何が解決できるのか
eslintが共通化できる(作るものには寄るが)
依存度が高いがパッケージとして別に分けたいとき
react-router
react-router-dom
react-router-native
react-router-config (?)
react-routerが大本のロジックで、それに付随し、DOMとNativeで派生する形になっている。
react-router-dom と react-router-native は違うライブラリであるが、react-router にメインロジックを書いているため、しっかりと作られたreact-routerを使用し、DOMやNativeの独自実装を分ける、という事が可能になります。
更良い点はしっかりと設計されているのであればライブラリが流用しやすいところにあります。
reactのサブセット、react-inkを例としてあげますが大本のreactは構造体でしかなく、適用先は何でも良いわけです。 native app (react-native)
cli app (react-ink)
dom (react-dom)
注意すべき点
バージョニング
依存元に破壊的変更を加えた際他も破壊的アップデートを加える必要が出てくる
設計として依存元は相当作り込まなければいけない
デバッグ方法
依存元はたいていロジカルな事を行うため、テストが必須になるケースが多い
というのも、共通化するのでDOMに依存しない部分を作成することが多め (例 react-dom reactの話をする)
実際にフロントを見ながら作成するフローを取れない場合があるので、その際開発の体験が損なわれる。
設計力が必要
縦割、横割、どちらも可能な設計手法なため
不便になってしまうこと
周知コスト
パッケージを導入/削除する際に従来の手順とは変わる
開発フローがシングルソースよりも難しい
より厳格に「責務を分ける必要があるかどうか」で話す必要が出てくる
こういうのってだいたい人によって宗派の違うから統一が難しい
ビルドタスクや、jestのconfigなどが込み入りやすい
jestやwebapckやrollupを記述する際に自分で書くケースが出てこなくもない
ArakiTakaki.icon 以外とreact-routerのランナーは雑かった
というかコレに関してはlerna run buildでいいのでは・・・・? ArakiTakaki.icon なんかもはや読む気にあまりなれない
まとめ
...ただ、lerna入れずにyarn workspaceのみを使用しているため、今週土日に書き換えます。
強み
JSの実実装以外に依存しない仕組みだけの提供が可能となりDRY
Reactの例
複数のレポジトリをまたぐ必要がなくなる
依存パッケージをまとめて管理できる
脆弱性の見つかったパッケージとか一斉アップデートかけれる
弱み
IssueとPR管理が大変
モノレポ開発のワークフローを固めなければいけない
バージョニングとか細かいところまでツメる必要が出てくる
所感と作りたいもの
カルーセルなんかを作る時はこういう分け方しても面白いのかも(react-routerっぽい感じ?)
packages
carousel-core
react-carousel
vue-carousel
dom-carousel (良い名前思いつかない)
Electron製品など開発する際に、プラグインを導入する形にして、案件特有のものを外だしとかももしかしたらできないかな・・・?
サイボウズのkintoneはそのような管理の仕方を取り入れているらしい packages
product-a
plugin-a
plugin-b
plugin-c
plugin-d
フロントとサーバーを完全分離させて開発して、interfaceの共通化とかもできそう
packages
frontend
server
interface
実装としてのinterfaceだから、揺れない+自動生成に頼らなくても良いから便利そう(そもそもTypeScriptでサーバー書く事になるがそれが許容できるのであればだが)
サーバーいっぱい作れそう(これはレポジトリ分けても良い気もする)
pacakges
graphql-server (parent)
service-api-a
service-api-b
service-api-c