剖析 npm ERR! Conflicting peer dependency

1,266 阅读3分钟

假如你的项目里包含子项目(packages), 且子项目 A 包含一个 peer dependency 依赖的包 xxx@1.2.1版本,而子项目 B 包含一个 peer dependency 依赖了同样的包,但是版本是 xxx@1.3.2

当你尝试通过npm 安装时,你可能会遇到一个常见的错误信息,上面写着 Conflicting peer dependency:xxx ,详细错误信息类似于:

Conflicting peer dependency: xxxx@1.2.1
node_modules/xxx
peer xxx@"^1.2.1" from 项目A
... ...

或者是直接报了如下错误: image.png

满屏的 npm ERR!, 意思是说无法解析依赖树。 它也「细心」地给了你解决方式: image.png 安装的时候,增加**--force or --legacy-peer-deps**参数

Why:为啥出现 peer dependency 冲突的错误呢?

这一切还要从 npm版本差异 说起,说之前先让我们了解一些peer dependency概念。

What: 什么是 peer dependency?

一个 peer dependency 依赖指定了该项目的这个包,要求父级环境具有这个包,而它自己不是直接依赖它。举例:项目 A 安装依赖 react@16.8:

{
    "dependencies": {
       "react": "^17.0.2",
       "libB": "^1.2.0"
    }
}

而 libB的 package.json 如下:

{
    "peerDependencies": {
       "react": ">=16.8.0"
    }
}

那么安装后的项目结构如下:

项目A
|
+---node_modules
    +---react
        package.json
    |
    +---libB
        package.json

那么为什么 libB 不把"react": "16.8.0"放到dependencies中呢?

假如 libB 放到dependencies的话,项目 A 安装后的结构如下:

项目A
|
+---node_modules
    +---react
        package.json
    |
    +---libB
        package.json
        +---react
            package.json

可以看到项目 A 安装了了两个不同版本的 react, 而peerDependencies仅有一个react版本。

那么peerDependencies的一个作用就是减少重复安装依赖

在了解了基础概念后,让我们看看 npm 不同版本间的peer诡异行为

npm 不同版本上 peer 诡异行为
  • 版本 1~3peerDependencies 会像 dependencies 一样,被自动安装。

  • 版本 4~6,由于重复数据删除算法的技术问题,npm停止支持 peerDependencies 的自动安装。如果出现依赖包版本冲突或缺失,只会发出警告,类似于:image.png

  • 版本 7,npm 通过依赖Arborist算法:

    1. 默认自动安装peerDependencies
    2. npm模块必须指定每个peer dependency的特定版本。

    与之前的NPM版本相比,NPM版本7或更高版本对peerDependencies的要求要严格得多。这就是是本文开头提到的Conflicting peer dependency错误的原因。

  • 版本 8,为了区别可选的 peer 与 必须的 peer,新增了 peerDependenciesMeta 字段来标记可选 peer。

到这里大家也知道罪魁祸首是谁了,下面让我们看看怎样解决这个 **Conflicting peer dependency 错误

修复 Conflicting peer dependency ERR

使用以下几个方案可以解决这个冲突问题:

  1. 升级冲突包

    检查npm返回的错误,找出导致错误的包,并使用 npm install 命令手动升级新版本。需要注意的是:升级到软件包的新版本可能需要大量的工作,特别是当涉及到主要的版本更改时。这可能会导致应用程序出现新的错误和不稳定

  2. 使用--legacy-peer-deps选项。

    --legacy-peer-deps 是在NPM 7中引入进来的选项,用来忽略peer dependency,并继续安装。它将告诉 npm 安装包时使用npm 6算法来解析peerDependencies,也就是不自动安装peer dependency

    为了避免每次启动 npm i 命令时都添加 --legacy-peer-deps 标志,你可以在项目的根文件夹中创建一个 .npmrc 文件,并将其初始化如下,npm i命令将自动包含 --legacy-peer-deps 标志

legacy-peer-deps=true
  1. 使用Yarn代替npm

    Yarn是npm的替代包管理器。具体来说,与npm相比,它有一个更有效的冲突解决系统。因此,在解决对等依赖时,Yarn使用了比NPM更好的算法。因此,切换到Yarn可能会解决这个问题

  2. 清理npm

    由于npm缓存模块中的问题导致的peer dependency错误。如果前面的方法都不起作用,请尝试进行一个干净的包安装。参考一下步骤:

    • 删除node_modules 文件夹中。
    • 删除package-lock.json
    • 清除 npm 缓存:npm cache clean --force
    • npm install