NPM 如何处理版本冲突?
考虑一个例子,我们安装了一个模块,比如 A。现在我们想安装另一个模块 B,B 依赖于 A,但问题是模块 B 所需的 A 版本与最初安装的 A 版本不同.那么 npm 将如何处理我们的应用程序依赖于模块 A 的两个不同版本的这种情况。这就是版本冲突产生的地方。该问题可以表示如下。
在上图中,我们可以看到模块 B 依赖于模块 A 的版本 2,但应用程序的根目录中已经包含版本 1 的模块 A。
让我们通过以下案例逐步了解这一点:
情况 1:模块 A 和 B 都没有任何依赖关系。
在这种情况下,npm 会简单地将模块添加为node_modules下的根依赖项。依赖树可以表示为:
情况 2:模块 A 没有依赖关系,模块 B 依赖于相同版本的 A。
在这种情况下,结构将保持与之前相同。 NPM 不会再次安装相同版本的模块 A 作为 B 的依赖项。因此,模块 A 只会被捆绑一次。依赖关系树将与前一种情况相同。
案例3:模块A没有依赖,模块B依赖A的不同版本。
Npm 按照 package.json 文件中列出的顺序安装依赖项。因此,它将首先遇到模块 A(版本 1)并将其安装为 node_modules 下的根依赖项。现在,当 npm 安装模块 B 时,它会检查模块 B 的依赖项是否已作为根依赖项安装。如果它们已经安装在 node_modules 下,npm 将跳过安装这些依赖项。但是在这种情况下,模块 B 需要不同版本的模块 A,并且 A 的第一个版本已经作为根依赖项存在,因此 npm 将安装模块 A(版本 2)作为模块 B 的依赖项,这意味着模块 B 将拥有其自己的 node_modules 副本,在该副本下将列出 A 的第二个版本。在输出中,模块 A 的两个版本都将存在。依赖树可以表示如下:
情况 4:模块 A 没有依赖关系,模块 B 和 C 都依赖于模块 A 的版本 2。
现在在这种情况下,npm 将首先安装模块 A(版本 1)作为 node_modules 下的根依赖项。模块 B 和 C 将拥有自己的 node_modules 副本,其中将列出模块 A(版本 2)。需要注意的是,在输出模块 A(版本 2)中将被捆绑两次,因为它分别作为 B 和 C 的依赖项存在。因此,输出包必须包含同一模块的同一版本的多个副本。依赖树将如下所示:
这就是 npm 通过为每个依赖项制作单独的 node_modules 副本来处理版本冲突的方式。
参考: http://npm.github.io/how-npm-works-docs/npm3/how-npm3-works.html