【webpack】初始化、构建、生成
初始化阶段
- 参数处理 合并默认参数和配置参数 校验配置 合并最终配置
- 创建
compiler
对象 - 处理用户定义的
plugins
调用plugin
的apply - 调用new
WebpackOptionsApply().apply
处理webpack
内置插件- 注入
EntryOptionPlugin
插件,处理entry配置 - 根据
devtool
的值,判断后续用哪个插件处理sourcemap
- 注入
runtimePlugin
,用于根据代码内容动态注入webpack
运行时
- 注入
compiler
实例创建成功compiler.compile()
构建阶段
handleModuleCreate
根据文件类型构建module
- 通过
loader-runner
的runloaders
将各类文件资源转换为js
- 通过
acorn
将js
解析为AST
- 遍历
AST
,在HarmonyExportDependencyParserPlugin
插件监听exportImportSpecifier
钩子,解读JS
文本对应的资源依赖 - 使用
module
对象的addDependency
将依赖对象加入到module
依赖列表 AST
遍历结束,调用module.handleParseResult
处理依赖列表- 对于新增的依赖 再通过第一步的
handleModuleCreate
创建module - 重复前面的操作。等所有的依赖处理完成,构建结束
生成阶段
在构建阶段生成的modules,在此阶段会生成chunks输出
- 构建本次编译的
chunkGraph
对象 - 遍历
compilation.modules
集合,将module
按照entry/动态引入
,分配给不同的chunk
对象 - 遍历完成后,得到完整的
chunks
集合对象,调用creatXxxAssets
方法 creatXxxAssets
方法遍历module/chunk,调用compilation.emitAssets
将assets
信息记录到compilation.assets
中- 触发
seal
回调,控制流回到compiler
对象
创建chunk
的过程示例:
const path = require("path");
module.exports = {
mode: "development",
context: path.join(__dirname),
entry: {
a: "./src/index-a.js",
b: "./src/index-b.js",
},
output: {
filename: "[name].js",
path: path.join(__dirname, "./dist"),
},
devtool: false,
target: "web",
plugins: [],
};
此时index-a中依赖c,动态引入d
index-b中依赖c,e
两个entry
文件分别生成各自的chunk
,动态导入的d也生成一个chunk
。chunk a
中包含index-a.js
和c
,chunk b
中包含index-b.js、c、e
。c
同时包含在两个chunk
中,无疑增大了项目体积。因此,webpack
提供了一些插件如SplitChunksPlugin
,在之前的基础上进一步优化chunk
结构