webpack构建的详细流程探底(3)
webpack函数中主要做了以下两个操作,
- 实例化 Compiler 类。该类继承自 Tapable 类,Tapable 是一个基于发布订阅的插件架构。webpack 便是基于Tapable的发布订阅模式实现的整个流程。Tapable 中通过 plugins 注册插件名,以及对应的回调函数,通过 apply,applyPlugins,applyPluginsWater,applyPluginsAsync等函数以不同的方式调用注册在某一插件下的回调。
- 通过WebpackOptionsApply 处理webpack compiler对象,通过
compiler.apply
的方式调用了一些必备插件,在这些插件中,注册了一些 plugins,在后面的编译过程中,通过调用一些插件的方式,去处理一些流程。
第三步:调用compiler的run的过程(Compiler.js)
run()调用
run函数中主要触发了before-run事件,在before-run事件的回调函数中触发了run事件,run事件中调用了readRecord函数读取文件,并调用compile()
函数进行编译。
compile()调用
compile函数中定义了编译的相关流程,主要有以下流程:
- 创建编译参数
- 触发 before-compile 事件,
- 触发 compile 事件,开始编译
- 创建 compilation对象,负责整个编译过程中具体细节的对象
- 触发 make 事件,开始创建模块和分析其依赖
- 根据入口配置的类型,决定是调用哪个plugin中的 make 事件的回调。如单入口的 entry,调用的是SingleEntryPlugin.js下 make 事件注册的回调函数,其他多入口同理。
- 调用 compilation 对象的 addEntry 函数,创建模块以及依赖。
- make 事件的回调函数中,通过seal 封装构建的结果
- run 方法中定义的 onCompiled回调函数被调用,完成emit过程,将结果写入至目标文件
compile函数的定义
compile(callback) { // 创建编译参数,包括模块工厂和编译依赖参数数组 const params = this.newCompilationParams(); // 触发before-compile 事件,开始整个编译过程 this.applyPluginsAsync("before-compile", params, err => { if(err) return callback(err); // 触发compile事件 this.applyPlugins("compile", params); // 构建compilation对象,compilation对象负责具体的编译细节 const compilation = this.newCompilation(params); // 触发make事件,对应的监听make事件的回调函数在不同的EntryPlugin中注册,比如singleEntryPlugin this.applyPluginsParallel("make", compilation, err => { if(err) return callback(err); compilation.finish(); compilation.seal(err => { if(err) return callback(err); this.applyPluginsAsync("after-compile", compilation, err => { if(err) return callback(err); return callback(null, compilation); }); }); }); }); }
【问题】make 事件触发后,有哪些插件中注册了make事件并得到了运行的机会呢?