
webpack 基础流程
核心构建流程

初始化
- 初始化参数:从配置文件、配置对象、
shell脚本中读取配置参数,与默认配置合并出最终配置 - 创建编译器对象:基于最终配置创建
compiler对象 - 初始化编译环境:注入内置插件、注册各种模块工厂、初始化
RuleSet集合、加载配置的插件等 - 开始编译:执行
compiler对象的run方法 - 循环遍历入口:根据配置的
entry找出所有的入口文件,调用compilition.addEntry将入口文件转换为dependence对象,也就是依赖关系。
开始构建
make执行编译:根据entry对应的dependence创建module对象,然后调用loader将模块转译为标准的js,再调用js解释器将内容转换为ast对象,从中找出该模块的依赖模块,然后在递归编译直到所有依赖文件都经过此步骤处理- 完成模块编译:上一步递归编译处理得到他们之间的依赖关系,构造出一个依赖关系图
打包输出
- 输出资源(
seal):根据入口和模块之间的依赖关系,组合成包含多个模块的Chunk,再把每个Chunk转换成单独的文件加入到输出列表,这里是可以修改输出内容的最后一步 - 写入文件到磁盘:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件写入到文件系统
以上就是从一个宏观的角度看一次构建的主流程和相关步骤,下面对名词做个简单的介绍
- entry:编译的入口,起点
Compiler:编译管理器,webpack启动之后会创建compiler对象,这个对象全局只存在一个,一直到整个构建任务结束为止。Compilation:单次编辑过程的管理器,比如:watch=true时,每次的文件内容变更触发重新编译时。都会创建一个新的这个对象Depenence:依赖对象,webpack基于这个寻找依赖关系,转换关系图Module:一切接模块,所有内容的操作都是基于模块的,是webpack的基本单位Chunk:由module打包组成的产物Loader:资源转换器,因为webpack只认识js模块Plugin:在打包过程中的扩展功能,让打包流程能做更多事情。
流程详解
初始化阶段
- 把
process.args和webpack.config.js合并成为用户配置 - 调用
validateSchema对配置经行校验 getNormalizedWebpackOptions+applyWebpackOptionsBaseDefaults合并出最终配置- 创建
compiler对象 - 遍历用户的
plugins集合数组,执行插件的apply方法来执行插件 - 调用
new WebpackOptionsApply().process方法,加载各种内置插件
主要是 WebpackOptionsApply 类,会自动执行 webpack 内置的各种插件,并会在初始化阶段根据配置内容动态注入对应的插件:
- 注入
EntryOptionPlugin插件,处理entry配置 - 根据
devtool值判断用什么插件处理sourcemap,可选的插件有:EvalSourceMapDevToolPlugin、SourceMapDevToolPlugin、EvalDevToolModulePlugin - 注入
RuntimePlugin,根据代码内容动态注入webpack运行时
这样 compiler 实例就被创建出来了,环境参数也设置好了,接着就是调用 compiler.compile 函数
js
// 取自 webpack/lib/compiler.js
compile(callback) {
const params = this.newCompilationParams();
this.hooks.beforeCompile.callAsync(params, err => {
// ...
const compilation = this.newCompilation(params);
this.hooks.make.callAsync(compilation, err => {
// ...
this.hooks.finishMake.callAsync(compilation, err => {
// ...
process.nextTick(() => {
compilation.finish(err => {
compilation.seal(err => {...});
});
});
});
});
});
}
