webpack系列1--循环依赖解析与处理方式总结

2022-04-09  本文已影响0人  范小饭_

文章首发公众号,欢迎关注
webpack系列1--循环依赖解析与处理方式总结

什么是循环依赖?

一般开发其实不太关注,也不太遇到循环依赖的情况,但是随着项目复杂度增加,尤其是依赖关系复杂的大项目,很容易出现循环依赖的情况,容易产生意想不到的问题,所以今后在编码过程中,要加强这方面的意识。

所谓循环依赖,简单来说,就是 a.js 依赖 b.js 而 b 的脚本执行,又依赖a.js。

用一个demo解释下什么是循环依赖:

webpack.config.js

module.exports = {
    entry: './main.js',
}

mian.js

import a from './a';
console.log(a);

a.js

import b from './b';
export default b;

b.js

import a from './a';
console.log('a:', a); 
export default 1;

执行编译后代码


image.png

webpack 的入口文件为 main.js,随后他们的引用方式为: main.js –> a.js –> b.js –> a.js –> b.js

问题就出在 a.js 被循环引用了,b.js 中导入的 a.js,其引用值为 undefined,虽然我们希望它得到最后的 1 结果。

为什么会发生循环依赖

上面的整个deme会被webpack编译成如下代码

image.png

这个是一个立即执行函数,当浏览器加载js后会被触发执行,立即函数的参数为一个对象,key为依赖的文件路径,value为该文件编译后的内容

并且将入口文件main.js 作为参数传入,执行webpack_require方法,开始整个项目代码的执行

image.png

在这个函数中,做了如下几个事

1、判断全局 installedModules 是否有对应的 moduleId 值,有的话就导出其引用

2、如果没有,就执行 modules[moduleId] 方法,最后返回该模块 module 的引用

也就是说它会执行对应依赖里面的代码,执行后将该依赖再保存到installedModules对象里,下次就不要再执行了

image.png

1、初次调用的时候,installedModules[moduleId] 为空,接着通过 modules[moduleId].call 执行对应的依赖代码。第一个被执行的就是入口文件main.js的代码

2、main.js 里导入了 a.js,则又会调用 webpack_require 方法

3、这里对 a.js 的调用并没有结束(返回值还没有拿到),由于 a.js 中又导入了 b.js,所以又会同上述步骤再执行 b.js 对应的函数。

4、但执行到b这里时就不同了( modules[b.js].call

5、b.js 文件中导入了 a.js 文件,导致 a.js 作为参数又会进入到 webpack_require 方法。

6、因为先前 webpack_require(a.js) 被执行过了,所以在 modules[b.js].call 环节执行 webpack_require(a.js) 中,installedModules[moduleId] 判断为 true 了:

7、而最开始第一次导入 a.js 时,其返回值还没有拿到,所以此时为 true 后,返回值就为 undefined ,这就是问题的出现原因。

image.png

怎么解决?

总结3种处理循环依赖的方法(也欢迎各位小伙伴补充)

未雨绸缪:介绍一个插件

circular-dependency-plugin

能够在编译过程中检测项目代码中是否存在循环依赖,如果存在循环依赖就会再控制台输出警告,建议再开发环境下可以配置一个,能够未雨绸缪,毕竟有时候当循环依赖的闭环太长的时候,肉眼是很难区分出来的。

image.png

欢迎小伙伴们补充

以上3种方法是实践中我用来处理循环依赖的,欢迎有其他方法的小伙伴补充哈

上一篇 下一篇

猜你喜欢

热点阅读