react脚本父文件夹nodemodule在子位置运行时出错



运行react脚本时,在子文件夹(c:Reposweb_app1api_ui)中构建(Create-React-App),该子文件夹有自己的package.jsonnode_modules文件夹等。我得到以下错误:

react-scripts build

There might be a problem with the project dependency tree.
It is likely not a bug in Create React App, but something you need to fix locally.
The react-scripts package provided by Create React App requires a dependency:
"babel-loader": "8.0.4"
Don't try to install it manually: your package manager does it automatically.
However, a different version of babel-loader was detected higher up in the tree:
c:Reposweb_app1node_modulesbabel-loader (version: 7.1.4)
  • 将父文件夹的(c:Reposweb_app1)babel加载程序更新到v8.0.4不是一个选项,因为web_app1依赖于babel加载程序v7.1.4
  • 删除c:\Repos\web_app1中的node_modules不是一个选项。这是父应用程序,需要它自己的node_modules
  • 我的修复是将SKIP_PREFLIGHT_CHECK=true添加到.env文件中。这看起来像是一个黑客攻击,我想要另一个修复方案,包括通过飞行前检查进行构建
  • 子文件夹(c:Reposweb_app1api_ui)中的package-lock.json具有正确的babel loader版本(8.0.4),那么它为什么要进入父文件夹呢

在子文件夹中构建react脚本时,是否有方法忽略父文件夹或更高树node_modules

这也让我很困惑,我做了一些研究,查看了react-scripts版本4.0.3的源代码。此版本需要babel-loader8.1.0。安装了storybook(需要版本^8.0.0)后,我们在顶级node_modules中获得了不同的babel-loader,因此我们最终得到:

|-src
|-node_modules
|
|-storybook 6.3.12
|-babel-loader 8.2.6
|-react-scripts 4.0.3
|
|-node_modules
|
|-babel-loader 8.1.0

我收到了很多人都看到的错误消息,我想,在react-scripts中使用babel-loader不应该在自己的node_modules(即版本8.1.0)中获得babel-loader吗?我可以多次删除node_modulespackage-lock.json,但问题似乎总是存在。

事实上,您在问题中如何描述它是包管理器(至少是npm)如何工作的,例如,从react-scripts导入babel-loader会从它自己的node_modules给它版本8.1.0。。。但我们忘记了两件事,这两件事加在一起会造成问题:

  • 包装吊装
  • 传递依赖关系

包装吊装

我不会详细说明包裹何时吊装,但它确实发生了。基本上,它相当于将依赖A的依赖包B添加到项目根node_modules(或一些其他父node_modules),而不是添加到Anode_modules

所以不是

|-src
|-node_modules
|
|-A
|
|-node_modules
|
|-B

我们得到。。。

|-src
|-node_modules
|
|-A
|
|-node_modules (might exist anyway)
|-B

由于npm是如何工作的(正如您在问题中正确理解的那样),如果在node_modules/A/node_modules中找不到B,它将在node_modules中查找使其工作的包。当许多包都需要兼容的依赖关系时,提升可以是一种优化,这样我们就可以只存储一个依赖关系,而不是存储N个类似版本。它还简化了项目根node_modules的文件夹结构,从而更易于调试。事实上,默认情况是提升任何可以提升的包裹,例如node_modules中不存在的包裹。

通常,退回到天真的策略,用";包在其自身的CCD_ 43〃中的所有依赖关系;,在包版本冲突时使用。这就是在具有两个不同版本的babel-loader的顶部示例中发生的情况;storybook实际上由几个包组成,其中多个包使用babel-loader版本^8.0.0。当在react-scripts之前安装storybook时,它会使用符合约束的最新版本的babel-loader,并将其提升到顶级node_modules。当安装react-scripts时,这会导致常见的问题。我有另一个具有相同设置的项目,但react-scripts是在storybook之前安装的。在那里,babel-loader版本8.1.0被提升,并且由于该包也满足storybook(^8.0.0)的要求,因此不需要更多的babel-loader。在这里,create-react-scripts没有抱怨。当然,npm可以自己计算出这个顺序,这从存储的角度来看也是最优的(只有一个babel-loader,而不是两个),但据我所知,npm在处理依赖关系时使用字母顺序。

传递依赖关系

即使包A是我的项目的依赖项,A也可以有自己的依赖项。这些是关于我的项目的可传递依赖项。

为什么它不起作用

react-script版本4.0.3的源代码中,文件verifyPackageTree负责运行导致问题中无聊错误消息的检查。这个文件在以后的预发行版中不再存在,但在它的顶部,我们发现了注释:

// We assume that having wrong versions of these
// in the tree will likely break your setup. 
// This is a relatively low-effort way to find common issues.

下面几排写着:

// These are packages most likely to break in practice.
// See https://github.com/facebook/create-react-app/issues/1795 for reasons why.
// I have not included Babel here because plugins typically don't import Babel (so it's not affected).

看看引用的线程,有一个关于当安装了不兼容的依赖项时create-react-app为什么会中断的讨论,以及与上面相同的问题为什么不起作用?

最后的结论似乎是,例如,如果react-scripts导入了一个已被提升的包X,则该包将不会驻留在react-scripts下的node_modules中,而是驻留在根node_modules中,其中(关于最上面的示例)还驻留了babel-loader版本8.2.6(与react-scriptsnode_modules文件夹中的8.1.0版本相反)。现在,如果X要导入babel-loader,它将得到错误的babel-loader,例如,不是预期的版本8.1.0,而是8.2.6。在线程中,这被认为是npm中的一个错误,尽管我不知道为什么它会是一个错误。也许,可能会有一些标志表明吊装包裹是否可以,因为如果完全吊装被认为是一个错误,这似乎是一种倒退。

因为create-react-app的编写者不知道某个依赖项是否被提升,所以他们实现了这个简单的检查,它会发出警告。对于高级用户,他们有机会选择不使用SKIP_PREFLIGHT_CHECK标志进行检查。此外,最好记住,错误来自create-react-app,而不是npm,因此它实际上没有说明npm是如何工作的,只是说明create-react-app的创建者认为的问题(最初确实同样令人困惑)。

最新更新