webpack4升级到webpack5后部分页面出现Uncaught (in promise) ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization的原因与解决

AzrDream / 2024-08-22 / 原文

循环依赖

当两个或多个模块相互引用时,就会发生 JavaScript 中的循环依赖(也称为循环依赖)。

这可以是直接引用(A -> B -> A):

直接依赖,即 A 从 B 进口,而 B 又从 A 进口。

或间接 ( A -> B -> C -> A):

直接依赖,即 A 从 B 进口,B 从 C 进口,C 从 A 进口。

虽然循环依赖可能不会直接导致错误,但它们几乎总是会带来意想不到的后果。这可能表现为TypeScript类型检查缓慢或开发服务器频繁出现“JavaScript 堆内存不足”崩溃,但很可能会引入运行时错误。Node.js 确实支持模块之间的循环 require/import 语句,但它很快就会变得混乱。在 Node.js 文档中

需要仔细规划才能使循环模块依赖关系在应用程序内正常工作。

处理循环依赖的最佳方法是完全避免它们。循环依赖通常是代码设计不良的标志,需要应尽可能重构和删除它们。

检查循环依赖

我使用circular-dependency-plugin来进行检查:

JavaScript
// webpack.config.js
const CircularDependencyPlugin = require("circular-dependency-plugin");

module.exports = {
  entry: "./src/index",
  plugins: [
    new CircularDependencyPlugin({
      // exclude detection of files based on a RegExp
      exclude: /a\.js|node_modules/,
      // add errors to webpack instead of warnings
      failOnError: true,
      // allow import cycles that include an asyncronous import,
      // e.g. via import(/* webpackMode: "weak" */ './file.js')
      allowAsyncCycles: false,
      // set the current working directory for displaying module paths
      cwd: process.cwd(),
    }),
  ],
};

会发现项目引入的各种循环依赖关系。循环依赖插件的输出

修复循环依赖

修复大型项目中的循环依赖关系可能要投入大量时间。因此,最好从一开始就使用循环依赖检查器,因为这样可以完全防止引入循环依赖关系。

实践

解决循环依赖导入问题并不总是有一个万能的解决方案。你只需要撸起袖子开始行动即可。

最终,归结为打破导入链。有几种方法可以消除循环依赖。对于较长的链,A -> B -> C -> D -> A如果删除其中一个引用(例如,引用D -> A),则循环引用模式将被打破。

对于更简单的模式,例如A -> B -> A,可能需要重构。也许可以将 中的模块B移至A。或者,可以将必要的代码提取到和引用的C。如果两个模块执行类似的行为,也可以将它们组合成单个模块。这需要根据每个导入的独特因素逐案确定,但一般行为应该保持不变。AB

修复大量循环依赖可能需要投入大量时间,但可以提高代码库的可维护性,并减少将来的错误。通过将循环依赖插件保留在 webpack 中,可以频繁运行该插件,并且在引入循环依赖后会立即发现它。