定義
ワークスペースプロトコルとは、モノレポ(一つのリポジトリに複数のパッケージが共存する構造)において、内部パッケージへの依存をバージョン文字列の代わりに "pkg": "workspace:*" のようにローカルソースへ直接リンクする記法である。公開(publish)の時点で、ワークスペースを理解するパッケージマネージャがこの記法を実際のバージョン範囲へ書き換えてレジストリにアップロードする。
つまり、開発中はローカルリンク、公開の瞬間には本物のバージョン——二つの顔を持つ。
なぜ必要か
一つのリポジトリの中でパッケージ @scope/ui が @scope/utils に依存しているとしよう。@scope/utils を ^1.0.0 のようにバージョンで固定すると、utils を一行直すたびにバージョンを上げ、再インストール・再リンクしなければローカルに反映されない。開発速度が大きく落ちる。
"@scope/utils": "workspace:*" と書けば、ローカルソースが即座にリンクされ、すぐに反映される。しかしこの workspace:* という文字列をそのまま npm にアップロードすると、インストールする外部利用者のパッケージマネージャは workspace:* を解釈できず、インストールが壊れる。そのため公開時には必ず実際のバージョンへ置換されなければならず、この置換はワークスペースを理解するコマンドによってのみ起こる。
仕組み
- 開発時:
installがworkspace:*の依存を lockfile にlink:../utilsの形で記録し、node_modulesにローカルパッケージをシンボリックリンクする。 - 公開時:
pnpm publish(または yarn)が tarball を作る直前にpackage.jsonのworkspace:*を対象パッケージの実際の公開バージョンへ置換する。例:workspace:*→^1.3.0。 - 順序: 依存グラフの葉(下位パッケージ)から publish しなければならない。そうすれば上位パッケージが参照する下位のバージョンが、すでにレジストリに存在する。
npm publish はこの置換を行わない——workspace:* が生のままアップロードされ、インストール不能な tarball になる。
実務での適用
公開前に pnpm pack で tarball を開き、package.json の依存バージョンが workspace:* ではなく実際の値へ置換されているかを目視で確認すれば、事故を防げる。
トレードオフ
- 得られるもの: ローカル開発速度(即時反映)、手動でのバージョン管理の排除、単一リポジトリでのアトミックな変更。
- 支払うもの: 公開パイプラインがワークスペース対応マネージャに縛られる。
npm publishの習慣、OIDC への期待、誤った順序——すべてが破綻しうる箇所になる。 - バージョン自動化ツール(release ツール)と組み合わせると便利だが、その分だけ CI の配線(ランナー・トークン・順序)が増える。
使うべきでない場合
- パッケージが一つだけ、あるいは互いに依存していないなら、ワークスペースプロトコルの利点はない。
- 公開を必ず
npm publishだけで行わなければならない制約があるならworkspace:*を使ってはならない——置換されない。
よくある間違い
npm publishで公開:workspace:*がそのままアップロードされ、外部インストールが壊れる。pnpm publishを使う。- 内部依存に存在しない外部バージョンを固定:
^1.0.0がレジストリにないと CI のinstallが 404。workspace:*に変えて relock する。 - 公開順序の逆転: 上位を先に上げると下位の最新バージョンを見つけられない。葉から上げる。
- OIDC への期待:
pnpm publishは OIDC 非対応 → 公開権限の自動化トークンがなければ 403。
関連概念
- [[library-esm-packaging-dangling-exports]] — 同じ公開パイプラインで export フィールドの欠落によって一緒に壊れる問題