3代npm中的冗余及解决方法

继续上一小节的例子,我们的程序依赖于两个模块:

  • A模块,依赖于B模块V 1.0
  • C模块,依赖于B模块V 2.0

想一下,如果我们安装另外一个模块,该模块也依赖于模块B,这个时候该如何选择版本呢。


示例

比如我们现在需要另外一个包,模块D。这个模块依赖于模块B V2.0,跟模块C一样,那么npm是如何工作的呢?

因为B V1.0已经安装在顶层依赖中,因此我们不能将B V2.0安装在顶层依赖。因此模块B V2.0依然是被安装在模块D的嵌套依赖中。即使我们已经将其安装在模块C中了。

如果一个二级的依赖被两个以上的模块引用,但这个二级的依赖不是安装在顶层上,它就回被安装在各自引用的模块嵌套中。

不过如果一个二级的依赖被两个以上的模块引用,但是安装在顶层上,那么它就不会被冗余安装,而是这个安装在顶层依赖会被多个模块所共享。

比如,我们现在还想安装一个模块E,模块E如同模块A一样,依赖于模块B V1.0。

因为模块B V1.0已经安装在顶层依赖中,这个时候我们就不用重复安装它了。而只是安装模块E,然后与模块A共享使用模块B V1.0。

现在,如果我们将模块A升级到2.0版本,这个时候模块A不再依赖模块B V1.0了,而是模块B V2.0了,那么npm会如何做呢?

关键是要去记住安装的顺序。

即使模块A在package.json中首先被安装,不过使用npm install意味着模块A V2.0是最后一个被安装的。

那么结果就是,当我们运行npm install mod-a@2 --save,npm3会如下工作:

  • 移除模块A V1.0
  • 安装模块A V2.0
  • 因为模块E还依赖于模块B V1.0,因此不会卸载模块B V1.0
  • 将模块B V2.0安装在模块A V2.0目录下的嵌套依赖中

最后一个例子,就是当我们也将模块E升级到V2.0,这个时候假设它也依赖于模块B V2.0了,如同模块A一般。

那么NPM2将会执行下面这些事情:

  • 移除模块E V1.0
  • 安装模块E V2.0
  • 移除模块B V1.0(因为没有其他模块依赖它)
  • 安装模块B V2.0作为顶层的依赖

不过各个模块还存在有模块B V2.0。如果我们想要清除这个荣誉的话,那么就需要运行下面的命令了:

npm dedupe

这条命令将会解决所有依赖于模块B V2.0的包的问题。它通过将这些包引用的模块B V2.0重定向到顶层依赖,然后移除各自的嵌套依赖中副本的模块B V2.0。


链接: https://fly63.com/course/21_1005