npm install --legacy-peer-deps 究竟是做什么的?何时推荐使用?有哪些潜在用例?

462

刚刚遇到了这个错误:

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: nexttwin@0.1.0
npm ERR! Found: react@17.0.1
npm ERR! node_modules/react
npm ERR!   react@"17.0.1" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0" from react-hook-mousetrap@2.0.4
npm ERR! node_modules/react-hook-mousetrap
npm ERR!   react-hook-mousetrap@"*" from the root project
npm ERR! 

我正在尝试安装的模块似乎与我所安装的不同版本的其它依赖项有冲突。看起来npm在这方面已经改变了行为,现在会让安装失败。

我该怎么办来修复这个问题?我不想因为这个问题降级我的React版本。

我知道有一个叫做--legacy-peer-deps的标志,但我不确定它具体是做什么的,是否建议使用它/潜在的缺点是什么?我觉得npm让安装失败肯定有原因。

这很奇怪,因为我一直在使用yarn,最近一切都很好。


24
我刚刚执行了 npm install xxxx --legacy-peer-deps 命令。安装成功了,但我不确定这样解决问题是否是一个好主意,因为我并不完全理解这个标志的含义,所以我想问一下。但是我还没有找到这个标志的真正作用!:( - antonwilhelm
10
我想知道 --legacy-peer-deps--force 有什么不同,因为我的 npm 推荐使用其中任何一种方式:npm ERR! Fix the upstream dependency conflict, or retry this command with --force, or --legacy-peer-deps。请将此内容翻译成通俗易懂的中文,但不要改变原意。 - Nate Anderson
3
@TheRedPea找到答案了吗?我的npm也显示它们是相同的,但我现在看到这个,我担心它们并不相同。 - Sammaye
1
没有,@Sammaye,我不认为我找到了答案。 - Nate Anderson
@antonwilhelm,你能找到这个问题的答案吗?因为我目前也遇到了同样的错误。 - David.E
我也遇到了同样的问题。17.0.1是比16.8.0更高的版本。为什么NPM认为这是一个冲突呢?这没有道理。 - DBZHOU
8个回答

607

简而言之:

  • NPM v7+默认安装peerDependencies以前的NPM版本则不是这样。
  • NPM模块必须命名特定版本的peerDependencies。
  • 如果您已经安装了一个peerDependency,但没有使用模块命名的版本,则NPM v7+会抛出错误。
  • 添加--legacy-peer-deps会忽略这个新要求,但可能引入破坏性的变化。

--legacy-peer-deps恢复了NPM v4到v6的peerDependency安装行为

可以这样理解这个标志,它并没有做什么新的事情;相反,它告诉NPM不要做一些新的事情,因为NPM v7现在默认安装peerDependencies

在许多情况下,这会导致版本冲突,从而破坏安装过程。

--legacy-peer-deps 标志是在 v7 版本中引入的,用于绕过 peerDependency 的自动安装;它告诉 NPM 忽略 peer deps 并继续安装。这就是 NPM v4 到 v6 版本的工作方式。
如果你对普通依赖和 peer 依赖之间的区别不清楚,这里有一些背景信息:
依赖 vs peerDependencies
依赖:NPM 模块在生产环境中需要的库或模块。(例如:我最近构建了一个模拟饼图的库,它使用 Chance.js 在指定范围内计算随机数;因此,Chance 是我的模块的一个依赖。)

peerDependencies: 一个peer dependency是指一个模块被设计用于与第三方软件库的特定版本或一组版本一起工作。它们类似于浏览器扩展和浏览器之间的关系。(例如:react-redux有两个非常合理的peerDependencies:react和redux。)

这个问题在一定程度上是由React v17+推动的

由于许多模块没有将React v17(或最近的React 18)作为peerDependency添加到其中,现在在v17 React应用程序中运行npm安装时普遍遇到“无法解析依赖树”错误。

只要一个模块(或其任何依赖项)将之前的React主要版本列为peerDependency,而没有明确包含React v17,就会触发此错误。

(注意:任何其他框架或库的主要版本更新也会出现类似的行为。)

如何检查任何给定模块的peerDependencies

NPM本身在给定模块的页面上不列出对等依赖项。然而,有一个简单的解决方法可以在安装之前或之后检查对等依赖项。只需运行以下命令:
npm info name-of-module peerDependencies
该命令将返回每个对等依赖项的名称以及所有兼容的版本。

5
非常好的解释!但是我仍然被“在我的根目录中的冲突对等依赖项:@angular/platform-browser-dynamic@11.2.13”所困惑。它显然与“@angular/fire@6.1.4”产生冲突,后者需要一个兼容版本的“peer @angular/platform-browser-dynamic@”^9.0.0 || ^10.0.0 || ^11.0.0" - 为什么会出现这个错误?它们似乎并没有发生冲突? - redevill
1
@VuTrongNghia 我不建议在生产环境中采用那种方法。 - Chris Perry
8
那么这个名称不应该改为 --dont-install-peer-deps 或类似的吗? - A dev
4
@Adev 我明白你的意思。在软件中命名是一个具有挑战性(并且高度主观)的任务。我个人更喜欢你的方法(可能会更简洁一些,比如 --ignore-peer-deps),无论怎样表述,其意图都比“legacy”更为明显。自私地说,如果这样做的话,我的投票可能就不会那么多了,但这是我能想到的唯一缺点 :3 - Chris Perry
1
这绝对值得点赞。感谢您用您的知识启迪我们,前辈。 - Andrey Vasilyev
显示剩余13条评论

105

这是我是如何解决这个问题的:

首先,了解发生了什么:react-hook-mousetrap正在寻找react@16.8.0,但它没有找到它。相反,它找到了@react17.0.1,这是一个更新的版本。由于某种原因mousetrap不喜欢这个更新版本,所以您收到了通知(这并不是什么大不了的事情,但他们决定值得停止构建)。

一种解决方案:强制安装mousetrap想要的特定版本的react

yarn add react@16.8.0

这样做的作用是将你的React版本回滚到一个稍旧但与Mousetrap兼容的版本。 你不会注意到任何区别,在未来的迭代中,希望Mousetrap会更新,这个问题就会消失。

另一个解决方案:做出一个彻底的决定,不安装任何旧版本的依赖项:

npm add xxxx --legacy-peer-deps

这个功能会忽略该包的旧依赖关系。它更加全面,可以为您做出许多决策。


23
--legacy-peer-deps 不会将任何依赖项回滚到任何版本。它只是不尝试自动安装对等依赖项。需要注意的是,此选项不会更改原有的意思。 - Daniel Tabuenca
1
@dtabuenc - 我已经更新了。如果您认为仍然不正确/误导,请编辑。谢谢。 - Izzi
我不理解的是,https://npm.anvaka.com/#/view/2d/react-hook-mousetrap 首先并没有显示这样的依赖关系! - redevill
有没有办法我们只需更改任何软件包的版本并仅使用npm install就可以完成呢? - Chanrithisak Phok
2
@redevill 很不幸,npmjs.com上没有显示对等依赖项,您需要查看库的package.json文件本身(https://github.com/olup/react-hook-mousetrap/blob/master/package.json#L30-L33)。 - Valentin
我应该使用什么代替xxxx,是React还是插件? - Zed

11

legacy-peer-deps

  • 默认值:false
  • 类型:布尔值

导致npm在构建软件包树时完全忽略peerDependencies,就像npm版本3到6一样。

如果由于过于严格的peerDependencies而无法安装软件包,则提供了一种解决该情况的方法。

这与--omit=peer不同,因为--omit=peer将避免在磁盘上解压缩peerDependencies,但仍将设计一个树,以便peerDependencies可以在正确的位置解压缩。

不建议使用legacy-peer-deps,因为它不会强制执行元依赖项可能依赖的peerDependencies合同。


如果您想继续使用legacy-peer-deps而无需在每个命令中添加标志,您可以在您的.npmrc中进行配置(可以在项目级别或全局级别上进行配置):

echo "legacy-peer-deps=true" >> .npmrc

npmrc

npm会从命令行、环境变量和npmrc文件中获取配置设置。

npm config命令可用于更新和编辑用户和全局npmrc文件的内容。


4
我使用yarn解决了以下问题,将以下内容添加到package.json中。
"resolutions": {
    "**/react": "17.0.2",
    "**/react-dom": "17.0.2"
},

3
有没有一种方法可以仅使用npm install并更改package.json中的任何软件包版本? - Chanrithisak Phok

3

如果您不想阻止安装旧的依赖项,可以通过强制运行脚本来使npm忽略这些警告。--force


2

--legacy-peer-deps 跳过安装所有的 peer 依赖项,并提醒开发者手动安装这些 peer 依赖项。当遇到 peer 依赖项冲突时,除了使用 --legacy-peer-deps,另一个选择是使用 --force
处理 peer 依赖项冲突的官方文档在this

p.s.
修正顶部答案:--legacy-peer-deps 恢复了从 NPM v3 到 v6 的 peerDependency 安装行为,而不是 v4 到 v6。


1
我在运行命令npm audit fix --force后遇到了依赖错误。
我使用了这个命令来修复错误npm add xxxx --legacy-peer-deps

1

另一种方法是将您的npm版本降级到版本6


3
您的回答可以通过添加支持信息来改善。请[编辑]以添加进一步的细节,例如引用或文献,以便他人可以确认您的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
3
  1. 这没有任何支持性的评论说明为什么版本6更好,或者降级会带来什么影响。
  2. 这建议回退到旧版本,这通常是不可取的,并且会有自己的问题。
- Scala Enthusiast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接