npm workspace + TypeScript project reference + リリース自動化の素振り
ここまでの変遷
バージョン | 構成 |
---|---|
v0.1.1 | lerna + TypeScript + Shipjs |
v1.0.0 | npm workspace + TypeScript project reference + Shipjs |
v2.0.0 | npm workspace + TypeScript project reference + release-drafter |
npm ci
npm workspaceの機能により、packages以下の依存は全て巻き上げられてrootのnode_modulesに集約される。また、packages間の依存は自動的に検知されてnode_modules内でシンボリックリンクに変換される。この挙動は npm ls
で見るとわかりやすい。
例として、providerに依存しているconsumerのpackage.jsonにproviderを追加する場合
lerna add
でいい感じにやってくれる。バージョンだけは正確に合わせる必要がある
npx lerna add @kesin11/[email protected] --scope @kesin11/monorepo-sandbox-consumer
npm i @kesin11/[email protected] -w @kesin11/monorepo-sandbox-consumer
lerna add
のように npm install
でいけるかと思いきや、registry.npmjs.orgにそんなパッケージは無いと怒られてしまう。
npm install
で入れる方法は分からなかったが、package.jsonのdependenciesに直接 "@kesin11/monorepo-sandbox-provider": "0.1.1"
と書いて npm install
を実行すればちゃんとsymlinkを貼ってくれてよしなに解決してくれる。やはりバージョンは合わせる必要がある
が、例えば ^0.1.0
のように解決される幅を広げた場合には最終的に依存している別のpackage.jsonのバージョンに解決できれば問題な
さそう。この例だと逆に 0.1.0
と固定した場合にはエラーになる。
npm run build
# = tsc -b
npm run build:clean
# = tsc -b --clean && tsc -b
TypeScriptのProject Referenceによってpackages以下を全てまとめてビルドしてくれる。
各パッケージが互いに依存しているので、それぞれのtsconfigのreferenceに依存しているパッケージへの参照を追加する必要がある。これは@monorepo-utils/workspaces-to-typescript-project-referencesによって自動的にメンテが可能。
全体をビルドするのでそこそこ時間がかかるが、tsc -b
はビルドキャッシュを活用できるので実際はそれほど困らないはず。また後述のjestによるテストを実行する前に依存しているパッケージも最新の状態でビルドされていないと結果がおかしくなってしまうので tsc -b --watch
で常時ビルドしておくのが安全かもしれない。
npm run test
# = npm run test --workspaces
npm workspaceの機能によって各packagesそれぞれの npm run test
が実行される。
注意点はpackageが他のpackageに依存している場合(例: packages/consumerはpackages/provider, packages/typesに依存している)は依存されている側があらかじめビルド済みで dist
に.jsや.d.tsが存在しないと型の解決ができなかったりimportできないので当然テストも動かない。
事前に全てが最新の状態にビルドされていないとテスト結果がおかしくなる可能性があることに注意する。
lerna versionで各packagesのバージョンを上げつつgit tagを作り、CHANGELOGを生成してGithub Releaseまで更新してくれる。 CHANGELOG生成 -> Github Releaseまで一気通貫で行われるため、shipjsのように手動でCHANGELOGを書き換えることはできない。
packagesが互いに依存している場合、自動でpackage.jsonのdependenciesを書き換えてくれるはず。
lerna version --conventional-commits
lerna publish from-package
v0.1.1のREADME参照
v1.0.0のREADME参照
npm version -ws major
のように npm verson
を実行すると全パッケージのバージョンを上げてくれる。昔はpackage-lock.jsonまでは更新していなかった気がするがいつの間にか同時に更新されるようになっていた。ただし、monorepoの各パッケージが互いに依存している場合にそれぞれの dependencies
のバージョンまでは上げてくれない。^1.0.0
の指定の場合はpatchとminorまでは問題ないがmajorを上げるときに npm install
がエラーになってしまう。
majorのときに手動で修正が必要になるのを避けるため、バージョン指定を "*"
にすることで制約を無しにしておく。workspaceを使っている場合はmonorepoのパッケージを参照するように npm install
されるので多分問題はないはず。参照できているかどうかは npm ls
で確認できる。
リリース作業は手動(workflow_dispatch)+ release-drafterで行う。release-drafterはGithub Releasesの作成とSemantic Versioningに基づく次バージョンの文字列を自動生成してくれるので、次バージョンの文字列を使用して npm version
でバージョンを更新する。
release-drafterはshipjsのようにツールが裏側で自動的に各種コマンドを実行するわけではないため、nodejs以外の言語でも使えるしnpmの標準的なフロー以外の作業が必要なリポジトリにも応用しやすいメリットがある。
release-drafterはSemantic Versioningの解決をshipjsのConventional Commitsではなく、pull-requestsのラベルを使用する。このルールはrelease-drafter.ymlで独自にカスタマイズを行っている。