dependencies、devDependencies、peerDependencies的区别,如何解决依赖包版本冲突

1,505 阅读4分钟

各种不同方式的依赖的区别

dependencies

  • 生产环境运行时需要的依赖
  • npm install 会下载这类型的依赖
  • npm install --production 会下载这类型的依赖
  • 第三方组件的dependencies,无论哪种环境都会被下载

devDependencies

  • 开发环境运行时需要的依赖
  • npm install 会下载这类型的依赖
  • npm install --production 不会下载这类型的依赖
  • 第三方组件的devDependencies,无论哪种环境都不会被下载

peerDependencies

  • 用来声明项目依赖包的版本范围
  • 通常用于告知用户项目运行时所依赖的某些库或框架的版本,确保安装的库版本与项目所依赖的版本一致,从而减少版本兼容性问题。

什么是依赖包版本冲突

假设

  • 你的项目依赖了A包,A包又依赖了C包的1.0版本
  • 你的项目还依赖了B包,B包又依赖了C包的2.0版本
你的项目-->A包-->C包(1.0)
你的项目-->B包-->C包(2.0)

那么此时的C包就存在版本冲突

如何看安装依赖包时,版本冲突的错误日志

通常版本冲突时的错误日志像下面的这个样子

image.png

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: archetype-backend-template@1.0.0
npm ERR! Found: @typescript-eslint/parser@6.21.0
npm ERR! node_modules/@typescript-eslint/parser
npm ERR!   dev @typescript-eslint/parser@"^6.16.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @typescript-eslint/parser@"^5.0.0" from @typescript-eslint/eslint-plugin@5.62.0
npm ERR! node_modules/@typescript-eslint/eslint-plugin
npm ERR!   dev @typescript-eslint/eslint-plugin@"^5.62.0" 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!
npm ERR! For a full report see:
npm ERR! E:\nodejs\node_cache\_logs\2024-02-18T05_11_27_479Z-eresolve-report.txt

npm ERR! A complete log of this run can be found in: E:\nodejs\node_cache\_logs\2024-02-18T05_11_27_479Z-debug-0.log
npm ERR! Found: @typescript-eslint/parser@6.21.0
npm ERR! node_modules/@typescript-eslint/parser
npm ERR!   dev @typescript-eslint/parser@"^6.16.0" from the root project

这里的root project就是指你的项目,dev 就是指你的devDependencies依赖,整句话的意思就是: 解析到了@typescript-eslint/parser@6.21.0的依赖,但从你的项目的devDependencies中找到的@typescript-eslint/parser的依赖的版本是@"^6.16.0

npm ERR! peer @typescript-eslint/parser@"^5.0.0" from @typescript-eslint/eslint-plugin@5.62.0
npm ERR! node_modules/@typescript-eslint/eslint-plugin
npm ERR!   dev @typescript-eslint/eslint-plugin@"^5.62.0" from the root project

peer是指peerDependencies, 完整的意思就是:从@typescript-eslint/eslint-plugin@5.62.0依赖的peerDependencies解析到的@typescript-eslint/parser的版本要求是^5.0.0,而你项目中devDependencies定义的@typescript-eslint/eslint-plugin版本是^5.62.0

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.

完整意思是: 修复依赖冲突或重试,或者使用"--force" 或 "--legacy-peer-deps"参数,用来接受错误的依赖

如何解决依赖包的版本冲突

分两种情况:

  • 遵循peerDependencies的相关约束,升级或降级版本依赖
  • 忽略peerDependencies相关约束,此时又分为两种情况
    • 一种是你的package.json已经设置好所有依赖包了。这时候你直接npm i --legacy-peer-deps即可
    • 一种是你正在一个个的安装依赖,但安装到某个依赖时,出现版本冲突,这时候你直接npm i xxx --legacy-peer-deps即可

使用npm i --legacy-peer-deps后的问题

你这次通过npm i --legacy-peer-deps安装完依赖之后,其他人如果使用npm i安装依赖,依然会出现版本冲突报错,那有什么办法解决呢?那就是在 package.json 中指定 overrides

比如:

package.json

{
...
  "overrides":{
    "@typescript-eslint/eslint-plugin":{
      "@typescript-eslint/parser":"$@typescript-eslint/parser"
    },
    "@vitejs/plugin-vue":{
      "vite":"$vite"
    },
  }
...
}

这里就表示@typescript-eslint/eslint-plugin包依赖的@typescript-eslint/parser, 使用项目中定义的版本号$xxx就表示使用项目package.json中的版本号

当然还有些文章中写的是使用resolutions字段,而非overrides, 那到底用哪个呢?

  • resolutions: 当你用yarn作为包管理器时,使用该字段
  • overrides: 当你使用npm作为包管理器时,使用该字段

补充: 关于npm ls的用法

npm ls是基于package-lock.json的内容显示依赖关系。也就是说必须存在package-lock.json这个文件,npm ls这个命令才有效

npm ls默认列出项目所有的依赖项,以及依赖项的子依赖

npm ls xxx列出所有依赖了xxx包的包, xxx包会被高亮为黄色

参考资料

巧用 package.json overrides / resolutions - 掘金 (juejin.cn)