-
被任意模块使用到的导出值,调用
exportInfo.setUsedConditionally
方法将其标记为已被使用。 -
exportInfo.setUsedConditionally
内部修改exportInfo._usedInRuntime
属性,记录该导出被如何使用 -
结束
上面是极度简化过的版本,中间还存在非常多的分支逻辑与复杂的集合操作,我们抓住重点:标记模块导出这一操作集中在 FlagDependencyUsagePlugin
插件中,执行结果最终会记录在模块导出语句对应的 exportInfo._usedInRuntime
字典中。
2.3 生成代码
经过前面的收集与标记步骤后,Webpack 已经在 ModuleGraph 体系中清楚地记录了每个模块都导出了哪些值,每个导出值又没那块模块所使用。接下来,Webpack 会根据导出值的使用情况生成不同的代码,例如:
重点关注 bar.js
文件,同样是导出值,bar
被 index.js
模块使用因此对应生成了 __webpack_require__.d
调用 "bar": ()=>(/* binding */ bar)
,作为对比 foo
则仅仅保留了定义语句,没有在 chunk 中生成对应的 export。
关于 W ebpack 产物的内容及
__webpack_require__.d
方法的含义,可参考 Webpack 原理系列六:彻底理解 Webpack 运行时 一文。
这一段生成逻辑均由导出语句对应的 HarmonyExportXXXDependency
类实现,大体的流程:
-
打包阶段,调用
HarmonyExportXXXDependency.Template.apply
方法生成代码 -
在
apply
方法内,读取 ModuleGraph 中存储的exportsInfo
信息,判断哪些导出值被使用,哪些未被使用 -
对已经被使用及未被使用的导出值,分别创建对应的
HarmonyExportInitFragment
对象,保存到initFragments
数组 -
遍历
initFragments
数组,生成最终结果
基本上,这一步的逻辑就是用前面收集好的 exportsInfo
对象未模块的导出值分别生成导出语句。
2.4 删除 Dead Code
经过前面几步操作之后,模块导出列表中未被使用的值都不会定义在 __webpack_exports__
对象中,形成一段不可能被执行的 Dead Code 效果,如上例中的 foo
变量: