Review
- 2024-09-15 07:33
[!Summary]
大致步骤
- 搭建结构,读取配置参数
- 用配置参数对象初始化
Compiler对象 - 挂载配置文件中的插件
- 执行
Compiler对象的run方法开始执行编译 - 根据配置文件中的
entry配置项找到所有的入口 - 从入口文件出发,调用配置的
loader规则,对各模块进行编译 - 找出此模块所依赖的模块,再对依赖模块进行编译
- 等所有模块都编译完成后,根据模块之间的依赖关系,组装代码块
chunk - 把各个代码块
chunk转换成一个一个文件加入到输出列表 - 确定好输出内容之后,根据配置的输出路径和文件名,将文件内容写入到文件系统
一、Introduction #
Compiler 是 Webpack 运行的引擎,应用运行时常驻,内部每次构建任务都会由一个 Compilation 实例完成
Compiler对象包含了Webpack环境的所有配置信息,包含options、loaders、plugins等信息。这个对象在 Webpack 启动时被实例化,它是全局唯一的,可以简单地将它理解为Webpack实例。
Compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。当Webpack以开发模式运行时,每当检测到一个文件发生变化,便有一次新的Compilation被创建。Compilation对象也提供了很多事件回调供插件进行扩展。通过Compilation也能读取到Compiler对象。
const webpack = require('webpack');
const compiler = webpack({
// ...
entry: './index.js',
output: { filename: 'bundle.js' }
}, (err, stats) => {
if (err) {
console.error(err);
return;
}
console.log(
stats.toString({
chunks: false, // Makes the build much quieter
colors: true, // Shows colors in the console
})
);
});
compiler.run((err, stats) => {
// ...
compiler.close((closeErr) => {
// ...
});
});整体流程分为3个阶段
- 初始化阶段
- 构建阶段
- 生成阶段
1、初始化阶段:Compiler, Compilation #
- 初始化参数:根据配置文件、命令行参数和 Webpack 默认配置,合并出完整的参数;
- 创建Compiler:用上面构建出的参数,创建 Compiler 对象(全局构建管理器)
- 初始化Plugins:遍历 plugins 数组,执行插件的 apply 方法;根据 Webpack 配置动态注入其它插件(比如根据 mode 值注入一些对 development 或 production 模式友好的插件)
- 开始编译:执行
compiler.run(),生成 ==Compilation== 对象(单次构建管理器,通常 build 只有1个,dev watch 模式,文件每次更新,都会重新创建 compilation 对象) - 生成Dependence:确定入口,根据 entry 配置,执行
compilation.addEntry(), 将入口模块转换成 Dependence 对象。

There is the
EntryOptionPluginwhich practically takes in theentryobject and creates anEntryPluginfor each item in the object. TheEntryPluginis also the place where anEntryDependencyis created.

2、构建阶段:ModuleGraph #
- 根据 entry 对应的 dependence 创建 Module 对象,调用相关 loader,将入口文件的内容转换成标准的 JS;
- 再调用 JS 解析器 Acorn,将 JS 转换成 AST,并从 AST 中获取该模块的依赖;
- 递归遍历依赖,重复上面两个步骤的处理,获取所有模块的标准 JS 内容和依赖,最终生成 ModuleGraph 对象。
3、生成阶段:Chunk, ChunkGraph, Asset #
- Chunk, ChunkGraph:遍历 ModuleGraph 对象,根据模块之间的关系,将模块封装进若干 Chunk 中,并根据 Chunk 之间的关系创建 ChunkGraph 对象;
- 优化:对每一个 Chunk 执行一些优化操作,比如
tree-shaking,splitChunks,compression等; - Asset:将最终处理好的内容,封装成 Asset,写入 output 配置的出口文件中。
开始进入构建时,编译器抛出事件,EntryPlugin根据入口配置往Compilation 注册入口 Dependency,Compilation 以此 Dependency 为起点进入构建阶段,每个模块构建都会经过四个阶段:
- 实例化模块
- 添加模块
- 构建模块
- 处理模块依赖