对等依赖的解析方式
pnpm 最好的特性之一是在一个项目中,特定版本的包总是只有一组依赖项。 但这个规则有一个例外 - 带有对等依赖项的包。
对等依赖项是从依赖关系图中更高层安装的依赖项中解析的,因为它们与其父级共享相同的版本。
这意味着如果 foo@1.0.0
有两个对等依赖(bar@^1
和 baz@^1
),那么它在同一个项目中可能
会有多个不同的依赖项集。
- foo-parent-1
- bar@1.0.0
- baz@1.0.0
- foo@1.0.0
- foo-parent-2
- bar@1.0.0
- baz@1.1.0
- foo@1.0.0
在上面的例子中,foo@1.0.0
被安装用于 foo-parent-1
和 foo-parent-2
。
两个包都有 bar
和 baz
,但它们依赖 baz
的不同版本。结果,foo@1.0.0
有两个不同的
依赖项集:一个带有 baz@1.0.0
,另一个带有 baz@1.1.0
。为了支持这些用例,pnpm 必须
针对不同的依赖项集创建 foo@1.0.0
的多个硬链接。
通常,如果一个包没有对等依赖项,它会被硬链接到一个 node_modules
文件夹中,
其中包含其依赖项的符号链接,如下所示:
node_modules
└── .pnpm
├── foo@1.0.0
│ └── node_modules
│ ├── foo
│ ├── qux -> ../../qux@1.0.0/node_modules/qux
│ └── plugh -> ../../plugh@1.0.0/node_modules/plugh
├── qux@1.0.0
├── plugh@1.0.0
但是,如果 foo
有对等依赖项,它可能会有多个依赖项集,
所以我们为不同的对等依赖项解析创建不同的集合:
node_modules
└── .pnpm
├── foo@1.0.0_bar@1.0.0+baz@1.0.0
│ └── node_modules
│ ├── foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ ├── baz -> ../../baz@1.0.0/node_modules/baz
│ ├── qux -> ../../qux@1.0.0/node_modules/qux
│ └── plugh -> ../../plugh@1.0.0/node_modules/plugh
├── foo@1.0.0_bar@1.0.0+baz@1.1.0
│ └── node_modules
│ ├── foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ ├── baz -> ../../baz@1.1.0/node_modules/baz
│ ├── qux -> ../../qux@1.0.0/node_modules/qux
│ └── plugh -> ../../plugh@1.0.0/node_modules/plugh
├── bar@1.0.0
├── baz@1.0.0
├── baz@1.1.0
├── qux@1.0.0
├── plugh@1.0.0
我们创建符号链接,要么链接到位于 foo@1.0.0_bar@1.0.0+baz@1.0.0
中的 foo
,
要么链接到位于 foo@1.0.0_bar@1.0.0+baz@1.1.0
中的 foo
。
因此,Node.js 模块解析器将找到正确的对等依赖项。
如果一个包没有对等依赖项,但有在依赖图中更高层解析的对等依赖项的依赖项,
那么该过渡依赖包可能会在项目中以不同的依赖项集出现。例如,有一个包 a@1.0.0
,
只有一个依赖项 b@1.0.0
。b@1.0.0
有一个对等依赖项 c@^1
。a@1.0.0
永远不会
解析 b@1.0.0
的对等依赖项,所以它也会依赖于 b@1.0.0
的对等依赖项。
下面是这种结构在 node_modules
中的样子。在这个例子中,a@1.0.0
需要在项目的
node_modules
中出现两次 - 一次解析为 c@1.0.0
,另一次解析为 c@1.1.0
。
node_modules
└── .pnpm
├── a@1.0.0_c@1.0.0
│ └── node_modules
│ ├── a
│ └── b -> ../../b@1.0.0_c@1.0.0/node_modules/b
├── a@1.0.0_c@1.1.0
│ └── node_modules
│ ├── a
│ └── b -> ../../b@1.0.0_c@1.1.0/node_modules/b
├── b@1.0.0_c@1.0.0
│ └── node_modules
│ ├── b
│ └── c -> ../../c@1.0.0/node_modules/c
├── b@1.0.0_c@1.1.0
│ └── node_modules
│ ├── b
│ └── c -> ../../c@1.1.0/node_modules/c
├── c@1.0.0
├── c@1.1.0