pnpmのworkspaceバージョン管理を強化したら、モノレポの依存関係がかなり整理された話

pnpm workspace内のバージョン管理機能が強化されたので、モノレポのcatalog機能を見直してみました。パッケージごとにバラバラだった依存バージョンがかなりスッキリしました。

🙌 結論から

pnpmのworkspace機能で、パッケージ間のバージョン管理がさらに強化されたので、モノレポの catalog 設定を見直してみました!

結果として、パッケージごとにバラバラだった依存バージョンが1箇所にまとまり、package.json を見るだけで「このバージョンで統一している」と一目で分かるようになりました(^^)

複数パッケージを抱えるモノレポを運用している人には、かなりおすすめできる整理方法だと思います。

💡 何が困っていたか

自分が触っているプロジェクトは、apps/ 配下に3つのアプリ、packages/ 配下に共通ライブラリが4つほどあるモノレポ構成です。

それぞれのパッケージが個別に package.jsondependencies を持っていたため、React や TypeScript のバージョンが微妙にズレていることがちょくちょくありました。

「片方のアプリだけ新しいReactの機能が使える」みたいな状態になっていて、バグなのか意図的なのか毎回確認する手間がかかっていたんですよね…。

依存を1つずつ手で揃えるのも現実的ではなかったので、workspace全体でバージョンを一元管理できる方法を探していました。

👀 catalog機能を整理してみた

pnpmには pnpm-workspace.yaml にバージョンを一元定義できる catalog という機能があります。

# pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"

catalog:
  react: ^19.2.0
  typescript: ^5.9.0
  zod: ^4.1.0

各パッケージ側では、バージョン番号の代わりに catalog: と書くだけで、この一元管理したバージョンを参照してくれます。

{
  "dependencies": {
    "react": "catalog:",
    "zod": "catalog:"
  }
}

最新のバージョン管理強化で、複数のカタログを用途別に切り分けられる catalogs(named catalog)もかなり使いやすくなっていて、「本番用の依存」と「実験的に試したい依存」を分けて管理できるようになっています🙌

✨ 使ってみた感想

一番助かったのは、Reactやtypescriptのバージョンを上げるときに、pnpm-workspace.yaml の1行を変えるだけで全パッケージに反映されるようになったことです。

以前は各パッケージの package.json を1つずつ開いてバージョンを書き換えていたので、それだけでかなり時間を取られていました。

導入してからは pnpm update を実行したときの差分も追いやすくなって、「どのパッケージのために上げたバージョンなのか」が分かりやすくなった感じがします。

移行作業自体も、既存の依存を1つずつ catalog: に置き換えていくだけなので、思ったより手間はかかりませんでした!

🔄 運用で気をつけていること

導入してみて感じたのは、catalogに入れる依存と、パッケージ固有で管理する依存の線引きが大事だということです。

React やTypeScriptのようにプロジェクト全体で揃えたいものはcatalog行き、逆に特定のパッケージだけが使う小さめのライブラリは、無理にcatalogへ入れずそのパッケージ側で管理するようにしています。

なんでもかんでもcatalogに寄せると、逆に pnpm-workspace.yaml が肥大化して見通しが悪くなるので、そこはバランスを意識するようにしました。

チームで運用する場合は、catalogに追加するときのルールを軽くドキュメント化しておくと、あとから見返しやすくなると思います。

🔧 catalogModeで強制する

運用ルールをドキュメント化しても、忙しいときは catalog: を使わずにバージョン番号を直接書いてしまうメンバーがどうしても出てきます。

そこでpnpm-workspace.yamlcatalogMode: strictを追加してみました。

catalogMode: strict

これを設定すると、catalogに登録済みの依存をpackage.json側で直接バージョン指定してインストールしようとした時点で、pnpmがエラーを出して止めてくれます。

ルールを口頭やドキュメントで伝えるだけより、インストール時点で強制されるのはかなり効果が大きいです。

私のチームでは、最初にcatalogを整備した週にこの設定も一緒に入れてしまいました。

あとから入れようとすると、その時点で直接バージョン指定してしまっている箇所を全部洗い出す手間が発生するので、catalog移行と同時にstrictにするのがいちばん楽だと感じました。

もう一つ試したのが、catalogs(named catalog)を使って**「安定版」と「実験用」**を分ける運用です。

catalog:
  react: ^19.2.0

catalogs:
  canary:
    react: ^19.3.0-canary.1

新しい機能を試したいアプリだけreact: "catalog:canary"と書けば、他のアプリは安定版のまま新機能だけ先行検証できます。

自分のチームだったら、と考えると、Renovateなどの自動更新botとの組み合わせも試してみたいところです。

catalogの1行だけを対象にPRを作ってくれるようになれば、複数パッケージに散らばったpackage.jsonを1つずつ見て回る作業自体がなくなるはずです。

パパ系Webエンジニア〜愛用ガジェット一覧 🛍️

この記事を書いている作業環境のガジェットを楽天ROOMにまとめています ✨ 在宅エンジニアのデスク作りの参考にどうぞ 🙌

👍 まとめ

pnpmのworkspaceバージョン管理を見直したことで、モノレポ内のバージョンのズレがかなり解消されました。

依存を1箇所で管理できるようになったことで、アップデート作業もだいぶ楽になった実感があります!

複数パッケージを抱えるモノレポでバージョン管理に意外とストレスを感じている人は、catalog を一度試してみてください。