ピアの解決方法
pnpmの最も優れた機能の1つは、プロジェクトが、特定バージョンの依存パッケージを常に1セットの依存関係として持つことです。 There is one exception from this rule, though - packages with peer dependencies.
ピア依存関係は、依存関係グラフの上位にインストールされている依存関係として解決されます。同じバージョンの依存パッケージを親として共有するからです。 つ まり、[email protected]に2つのピア依存関係があるとき (bar@^1およびbaz@^1) 、同じプロジェクトに複数の依存関係のセットが存在することになるのです。
- foo-parent-1
- [email protected]
- [email protected]
- [email protected]
- foo-parent-2
- [email protected]
- [email protected]
- [email protected]
前の例で は[email protected]がfoo-parent-1とfoo-parent-2にインストールされています。 どちらのパッケージにもbarとbazが存在しますが、bazのバージョンが異なります。 結果として、[email protected]は2つの依存関係のセットを持つことになります。片方のセットには[email protected]が、もう片方のセットには[email protected]が含まれています。 このようなユースケースに対応するため、pnpmは複数の依存関係のセットについて、[email protected]のハードリンクを作成します。
ピア依存関係を持たないパッケージは、node_modulesフォルダの中で他の依存パッケージに対するシンボリックリンクの隣にハードリンクを作成します。
node_modules
└── .pnpm
├── [email protected]
│ └── node_modules
│ ├── foo
│ ├── qux -> ../../[email protected]/node_modules/qux
│ └── plugh -> ../../[email protected]/node_modules/plugh
├── [email protected]
├── [email protected]
しかし、パッケージfooがピア依存関係を持つ場合、おそらく依存関係のセットは複数になります。pnpmはピア依存関係の解決結果に対する、それぞれの依存関係のセットを作成します。
node_modules
└── .pnpm
├── [email protected][email protected][email protected]
│ └── node_modules
│ ├── foo
│ ├── bar -> ../../[email protected]/node_modules/bar
│ ├── baz -> ../../[email protected]/node_modules/baz
│ ├── qux -> ../../[email protected]/node_modules/qux
│ └── plugh -> ../../[email protected]/node_modules/plugh
├── [email protected][email protected][email protected]
│ └── node_modules
│ ├── foo
│ ├── bar -> ../../[email protected]/node_modules/bar
│ ├── baz -> ../../[email protected]/node_modules/baz
│ ├── qux -> ../../[email protected]/node_modules/qux
│ └── plugh -> ../../[email protected]/node_modules/plugh
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
pnpmは[email protected][email protected][email protected]と[email protected][email protected][email protected]のそれぞれに、fooのシンボリックリンクを作成します。 結果として、Node.jsのモジュールリゾルバは正しいピア依存関係を発見できるようになります。
ピア依存関係を持たないパッケージでも、そのパッケージの依存関係が持つピア依存関係は、依存関係グラフの上位で解決されることになります。すると、推移的依存関係となるパッケージが、プロジェクトの複数の依存関係のセットとして表れることになります。 例えば、パッケージ[email protected]が1つの依存関係[email protected]を持っているとしましょう。 [email protected]はピア依存関係c@^1を持っています。 [email protected]が[email protected]のピア依存関係を解決することはありません。ですから、[email protected]のピア依存関係も同じように依存関係として追加されます。
node_modulesの構造がどうなるのか見てみましょう。 ここでは、[email protected]はプロジェクトのnode_modulesに2回登場しなければなりません。1つは[email protected]を解決するため、もう1つは[email protected]を解決するためです。
node_modules
└── .pnpm
├── [email protected][email protected]
│ └── node_modules
│ ├── a
│ └── b -> ../../[email protected][email protected]/node_modules/b
├── [email protected][email protected]
│ └── node_modules
│ ├── a
│ └── b -> ../../[email protected][email protected]/node_modules/b
├── [email protected][email protected]
│ └── node_modules
│ ├── b
│ └── c -> ../../[email protected]/node_modules/c
├── [email protected][email protected]
│ └── node_modules
│ ├── b
│ └── c -> ../../[email protected]/node_modules/c
├── [email protected]
├── [email protected]