有时候你可能会遇到依赖包版本的冲突问题,项目依赖了两个不同版本的同一个依赖包,这时候就可能会出现问题,例如,我们有以下包及其依赖项:
package-a@1.0.0
|_ package-d1@1.0.0
|_ package-d2@1.0.0
package-a@2.0.0
|_ package-d1@2.0.0
|_ package-d2@1.0.0
package-b@1.0.0
|_ package-d1@2.0.0
|_ package-d2@1.0.0
package-c@1.0.0
|_ package-a@2.0.0
|_ package-d1@2.0.0
|_ package-d2@1.0.0
此时你可能发现package-d1、package-d2等node_moudles中的子包需要更新(下面我们称其为间接依赖包),但又不能改变package-a、package-b、package-c等直接依赖的包,你会怎么做呢?
答案是,你可以使用yarn的resolutions字段解决这个问题,resolutions允许你指定一个特定的依赖包版本,以便确保在项目中使用的所有依赖包都使用相同的版本。它可以在package.json文件中定义,用于覆盖其他依赖包的版本。在以下情况下,你可能需要使用yarn的resolutions:
- 当你遇到依赖包版本冲突时,使用resolutions可以解决这些冲突。
- 当你需要强制使用一个特定版本的依赖包时,使用resolutions可以实现这一点。
- 当你需要升级依赖包版本时,使用resolutions可以指定一个新版本,以确保它与其他依赖包兼容。
下面我们来具体看看如何设置resolutions。
更新所有指定的间接依赖包
假如你想要更新所有名为package-d1的间接依赖包,你可以在package.json中按下面这样设置:
// package.json
"dependencies": {
"package-a": "1.0.0",
"package-b": "1.0.0"
},
"resolutions": {
"**/package-d1": "2.0.0"
}
yarn将用于package-d1@2.0.0每个嵌套的依赖项,并且通过不重复安装package-d1 来按照预期对文件夹进行操作。
更新指定依赖包的依赖包
也可能你只希望更某个特定位置的间接依赖包,你可以通过指定依赖包来定位它,如下:
// package.json
"dependencies": {
"package-a": "1.0.0",
"package-b": "1.0.0"
},
"resolutions": {
"package-a/package-d1": "3.0.0"
}
这样设置,yarn 将package-d1@3.0.0只用于package-a并且package-b仍然有package-d1@2.0.0它自己的node_modules。
当一个依赖包被直接和间接依赖时
例如我们开头的包结构中,package-a被项目直接依赖,同时被package-c依赖时,如果你只希望更新被package-c依赖的间接依赖包,你可以按下面这样设置:
// package.json
"dependencies": {
"package-a": "1.0.0",
"package-c": "1.0.0"
},
"resolutions": {
"**/package-a": "3.0.0"
}
直接依赖包package-a还是保持1.0.0,只是package-c中的package-a会被更新为3.0.0。
无效设置
如果你未指定间接依赖包所在的路径,而是直接写间接依赖包名的话,这样的设置是无效的。
// package.json
"dependencies": {
"package-a": "1.0.0",
"package-c": "1.0.0"
},
"resolutions": {
"package-a": "3.0.0"
}
规律总结
你应该总是使用 glob 模式来设置,以下为resolutions的设置总结:
a/b表示项目依赖a的直接嵌套依赖b。**/a/b表示项目所有依赖的直接嵌套依赖b和嵌套依赖a。a/**/b表示项目的依赖a的所有嵌套依赖b。**/a表示项目的所有嵌套依赖a。a是**/a的别名(为了追溯兼容性,因为如果它不是这样的别名,它就没有任何意义,因为它代表了一个非嵌套的项目依赖项,它不能被覆盖为下面解释)。**表示项目的所有嵌套依赖项。