最終更新: a few seconds agoRemove Netlify-related code from main (grafted, HEAD)

NPM Workspaces を使った Monorepo 化について

Lerna 版の記事はこちらに残してあります

概要

Lerna を使った monorepo はいろいろと問題があり NPM 7 との相性も悪そうなので NPM Workspaces に切り替える。

2021 年 2 月に Workspaces 機能の入った NPM 7.0 がリリースされた。2021 年 5 月リリースの NPM 7.14 辺りから個別パッケージのインストールや削除についてもサポートされており、Lerna の機能のうち大部分は代替できるようになっている。

ただしこの機能が使えるのが NPM 7 以降なので、Node 12 ~ 14 を使っている場合でも NPM だけは 7.14 アップデートする必要がある。

基本的には lerna コマンドを使ってやっていた作業が一通り npm でできるようになる。--scope=... オプションは --workspace=... オプションに変わる(-w でも同じ)。

Hoisting について

モノレポにおける hoist(巻き上げ)とは、複数のパッケージで共通に利用されている dependencies を、個別パッケージごとではなくルートの node_modules に 1 回だけインストールされるようにする操作のことであり、CIRCUS の開発においては必須。これがないと、import React from 'react' した時に実際にインポートされる React が、別の場所にインストールされた別の React になってしまい、それによりフックが動かないなどの酷い不具合に遭遇する。

Lerna では --hoist オプションを明示的に渡す必要があったが、NPM Workspaces では自動で hoist されるので --hoist のようなオプションは不要。ただし NPM 操作は monorepo のリポジトリルートで行うこと。

新しいワークフロー

グローバルに NPM 7.14 以降をインストールする(Node 12, 14 などを使っている場合にのみ必要)

npm install -g npm@latest

# version 7.14 以降であることを確認
npm --version

以下、すべての NPM 操作は monorepo のリポジトリルートで行う。個別ディレクトリ(packages/circus-api 配下など)に cd してから作業をしないこと。

全体の依存物のインストール

npm ci

個別パッケージで何かをインストール

npm install パッケージ名 --workspace=@utrad-ical/circus-api

# または短く

npm i パッケージ名 -w @utrad-ical/circus-api

cd packages/circus-apinpm install パッケージ名 とすると不具合の原因になるので monorepo のルートで行うこと。以下同様。

全パッケージで何かを最新版にアップデート

npm update パッケージ名 --workspaces

複数のリポジトリで使われている依存物をバージョンを同期しながらアップデートしたい場合などに。

あるパッケージから依存を削除する

npm remove パッケージ名 --workspace=@utrad-ical/circus-api

ちなみに Lerna にはこの機能がなかった。

全サブパッケージから依存を削除する

npm remove パッケージ名 --workspaces

個々のパッケージでスクリプトを走らせる

個別にやる場合(単に個別パッケージに cd してから普通に走らせるのでも多分同じ)

npm run スクリプト名 --workspace=@utrad-ical/circus-api

全パッケージで行う場合

npm run スクリプト名 --if-present --workspaces