【Webpack-有趣设计】

循环依赖导致模块导出为空对象

const fn = lazyFunction(() => require("./webpack")); 	// lib\index.js 128

初看可能不会将它和解决循环依赖导致的导出模块为空对象联系在一起,不过你可以试着这样子修改这行代码

const fn = require("./webpack");

然后重新启动debugger,你会发现一个报错,说webpack.ProvidePlugin is not a constructor在这里插入图片描述
然后我们跟着这个compiler溯源发现,这里的compiler.webpack到赋值处
在这里插入图片描述
Compiler.js文件中的webpack值来源于导入

const webpack = require("."); //lib\Compiler.js 17, 解释一下这里的.导入的是./index.js文件

我们的index.js中存在这行代码

get Compiler() {
	return require("./Compiler");
}, // lib\index.js 189-191

从这里我们可以看出 index.js 导入了 Compiler.js。然后Compiler.js又导入了index.js。这样子就产生了循环依赖。循环依赖会导致模块还没加载完成,从而导致了导出的是空对象的情况。

模块导入收集以及构建缓存

该文章的开始构建部分中我们了解到了构建过程中的函数调用,对于当前模块导入的依赖进行分析,然后递归出链式的导入依赖,从this._processModuleDependencies (任务队列调用-模块依赖)调用开始

_processModuleDependencies() {
	// ...其它逻辑
	this.handleModuleCreation() // 递归的开始,Entry逻辑中编译部分亦是通过这个方法。
} // lib\Compilation.js 1593-1873

可以在这部分代码中看到sortedDependencies,这个变量用来收集上一个模块中的dependencies(模块依赖数组),这个数组的产生一定离不开对于当前模块解析。
承接上篇文章的编译部分,build之后的ast处理逻辑以及dep收集

当前模块解析模块依赖逻辑
└── module.build (模块对应的解析处理实例, 大多数是NormalModule,lib\NormalModule.js)
    └── (this.parser).parse (_.doBuild最后的入参,一个回调函数 1357. (this.parser),这里的parser是当前实例的属性值,是在链式执行中通过发布订阅赋予的值, javascript/esm 对应 JavascriptParser.apply中发布方法产生的返回值)
        └── JavascriptParser._parse
            └── acorn.parse (三方库acorn)

在这里插入图片描述
下面是借助acorn.parse分析简单字符串的输出,可以看出esm的导入type是"ImportDeclaration",表达式声明的type是"ExpressionStatement"。由此可以区分出当前模块依赖的模块是哪些,然后通过后续的逻辑启用递归。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值