刘勇虎的官方网站
网站内容包含大前端、服务器开发、Python开发、iOS开发、Android开发、网站维护等技术文章。专注于分享技术经验,职业心得体会,IT优秀文章与教程创作。
Stay hungry,Stay foolish,Stay young
起因是开发时的一个报错信息:Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
。
由于报错信息不明确,网上也搜不到明确的原因解释和解决方法,所以自行排查了很久才逐渐找到原因。要说怎么排查,就是最笨的也是最有效的“代码删除法”,即从入口文件开始一行行删代码,直到定位到具体出错位置,然后凭借自身知识和经验判断出问题原因。
原因就是import的循环引用导致webpack无法正确解析。
最简单的 a 引用了 b,b 又引用了 a,这就产生了循环引用。
复杂点的无非就是链路长一些,例如 a -> b -> c -> d -> a。
循环引用可能会导致内存栈溢出。但也不是一定会有问题,比如 b 导出了两个方法,a 引用的是 b 导出的方法 fn1,而 b 是在方法 fn2 里引用的
a,这种情况其实是不会有问题的。
但由于可能的风险,且难以发现,所以编写代码时还是尽量规避使用循环引用。
利用 webpack 的插件 circular-dependency-plugin 来排查项目中的循环引用问题非常方便。
(并非所有的循环引用都会有问题,所以这个插件建议在需要排查问题时使用,开发时是否开启看个人需要。)
```
npm i circular-dependency-plugin -D
```
const CircularDependencyPlugin = require('circular-dependency-plugin')
export default {
...,
plugins: [
...,
new CircularDependencyPlugin(
{
exclude: /node_modules/,
include: /src/,
failOnError: false,
allowAsyncCycles: false,
cwd: process.cwd(),
}
),
]
}
ESM(es
modules,即es6模块化)是编译时加载,和commonJs的运行时加载不同。esm是尽量的静态化,编译时就能确定模块的依赖关系,正因为此,esm能够通过静态分析进行tree
shaking优化。
代码示例:
import a from './a'
console.log(a)
console.log('执行a')
import b from './b'
console.log(b)
console.log('导入b之后')
export default '我是a模块'
console.log('执行b')
import a from './a'
console.log(a)
console.log('导入a之后')
export default '我是b模块'
// main.js里import了a,先进到a解析
// import语句提前解析,a里import了b,所以暂停a的解析,进到b解析
// b里import了a,但a此时还未执行完,拿到的a值是undefined,然后往下继续解析b
b.js:1 执行b
b.js:3 undefined
b.js:4 导入a之后
// b解析完并拿到了b的导出结果,开始回到a里继续往下解析
a.js:1 执行a
a.js:3 我是b模块
a.js:4 导入b之后
// a解析完后,回到main.js解析执行
main.js:2 我是a模块
esm的import命令是在编译阶段就执行,优先于自身内容执行。
esm并不关心是否存在循环引用,只是生成一个指向被加载模块的引用,代码未执行时,这个引用的值就是undefined。
即使 esm 里循环引用没有异常,在webpack编译时可能也会报错,毕竟webpack会把 esm 降级为 es5,降级处理方式上可能会有一定的差异。
同样的上述示例代码,webpack(v5.64.4)处理后在执行console.log(a)
语句时就会出现异常报错:Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
。
就是把有循环引用的地方抽离到另一单独文件里,换句话说就是不使用循环引用。
把之前默认的导出对象改成导出函数的形式,从函数返回值里取导出结果。
由于每一个函数都会形成一个单独的局部作用域,不同的作用域有着不同的数据引用地址。
这样每次引入的结果都是一个新的引用,不会冲突,这种情况webpack也能正常的处理。
参考:
https://blog.csdn.net/u010059669/article/details/122876351
https://developer.aliyun.com/article/883077