运行react脚本时,在子文件夹(c:Reposweb_app1api_ui)
中构建(Create-React-App)
,该子文件夹有自己的package.json
、node_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-loader
与8.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_modules
和package-lock.json
,但问题似乎总是存在。
事实上,您在问题中如何描述它是包管理器(至少是npm
)如何工作的,例如,从react-scripts
导入babel-loader
会从它自己的node_modules
给它版本8.1.0
。。。但我们忘记了两件事,这两件事加在一起会造成问题:
- 包装吊装
- 传递依赖关系
包装吊装
我不会详细说明包裹何时吊装,但它确实发生了。基本上,它相当于将依赖A
的依赖包B
添加到项目根node_modules
(或一些其他父node_modules
),而不是添加到A
的node_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-scripts
的node_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
的创建者认为的问题(最初确实同样令人困惑)。