npm ERR! ERESOLVE unable to resolve dependency tree 问题解决
背景
升级npm后启动,npm i
安装依赖不成功,报如下错误:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: baokao@1.0.0
npm ERR! Found: eslint@5.16.0
npm ERR! node_modules/eslint
npm ERR! dev eslint@"^5.16.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer eslint@">=1.6.0 <5.0.0" from eslint-loader@1.9.0
npm ERR! node_modules/eslint-loader
npm ERR! dev eslint-loader@"^1.7.1" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users\13576\AppData\Local\npm-cache\eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\13576\AppData\Local\npm-cache\_logs\2022-07-21T03_00_14_019Z-debug-0.log
解决方式
执行 npm install --legacy-peer-deps
问题原因探索
假设我们现在有一个HelloHWCloud工程,已经在其根目录下的package.json文件中的dependencies字段里声明了packageA作为依赖,而其下面有两个项目app_A和app_B,它们也依赖packageA。如果我们用dependencies来声明,那么npm install安装完项目之后的依赖结构如下图所示:
├── HelloHWCloud
│ └── node_modules
│ ├── packageA
│ ├── app_A
│ │ └── nodule_modules
│ │ └── packageA
│ └── app_B
│ │ └── nodule_modules
│ │ └── packageA
从上图可以看出,packageA依赖包被安装了3次,造成了2次安装冗余。
而如果采用peerDepenedency来下载,就可以避免这个核心依赖库被重复下载的问题。
还是上面那个场景,我们在项目app_A和app_B的package.json文件里的peerDependencies字段声明一下核心依赖库packageA,然后在根目录的package.json文件里的package.json文件里的dependencies字段也声明一下packageA。接着再执行npm install,生成的依赖结构就会如下图所示:
├── HelloHWCloud
│ └── node_modules
│ ├── packageA
│ ├── app_A
│ └── app_B
如上图所示,packageA就只会被安装一次。因此,npm 从版本v7开始,install就默认以peerDependencies的方式去下载了。
策略如下:
- 如果用户在根目录的package.json文件里显式依赖了核心库,那么各个子项目里的peerDepenedencies声明就可以忽略
- 如果用户没有显式依赖核心库,那么就按照子项目的peerDepenedencies中声明的版本将依赖安装到项目根目录里
方式2,就会导致一个问题:用户依赖的包版本与各个子项目依赖的包版本相互不兼容,那么就会报错(无法解析依赖树的问题(依赖冲突))让用户自行去修复,因而导致安装过程的中断。(因为是从npm v7引入的,因此npm v3-v6就不会发生这个错误)
npm install --legacy-peer-deps
命令用于绕过peerDependency里依赖的自动安装;它告诉npm忽略项目中引入的各个依赖模块之间依赖相同但版本不同的问题,以npm v3-v6的方式去继续执行安装操作。
所以其实该命令并没有真的解决冲突,而是忽略了冲突,以“过时”(v3-v6)的方式进行下载操作。