承接上篇讲解到了webpack-cli/bin/cli.js文件中的compiler.run(),如果没有看过上篇文章的小伙伴建议先回过头简单过一遍,最接地气的webpack源码解析(一)。
将按照主线讲解webpack执行入口、构建前准备阶段、编译构建阶段、构建后优化阶段、文件输出阶段这五部分,本篇主要讲解构建前的准备阶段,由于在webpack-cli/bin/cli.js中最后是引入并且实例化webpack,const webpack = require("webpack");
,说明构建前的准备阶段主要是在webpack文件夹内。
这里说明一下针对cjs的require语法,引入的其实是依赖包里的入口文件,也就是package.json里main字段对应的文件"main": "lib/webpack.js"
。
webpack/lib/webpack.js
const Compiler = require("./Compiler");
const webpack = (options, callback) => {
options = new WebpackOptionsDefaulter().process(options);
compiler = new Compiler(options.context);
compiler.options = options;
new NodeEnvironmentPlugin({
infrastructureLogging: options.infrastructureLogging
}).apply(compiler);
if (options.plugins && Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
if (typeof plugin === "function") {
plugin.call(compiler, compiler);
} else {
plugin.apply(compiler);
}
}
}
compiler.hooks.environment.call();
compiler.hooks.afterEnvironment.call();
compiler.options = new WebpackOptionsApply().process(options, compiler);
return compiler;
}
exports = module.exports = webpack;
首先根据配置项参数初始化webpack的默认配置WebpackOptionsDefaulter()
,然后使用options实例化Complier得到解析器对象,然后初始化构建过程的node环境NodeEnvironmentPlugin
,注册用户自定义的各个插件,再注册webpack内置的各个插件WebpackOptionsApply()
,最后返回compiler。
这里主要是进行webpack构建前的准备阶段,数据初始化和环境搭建,特别说明一下WebpackOptionsApply()
这个函数内做了很多内置插件的注册工作
// webpack/lib/WebpackOptionsApply.js
class WebpackOptionsApply extends OptionsApply {
new EntryOptionPlugin().apply(compiler);
compiler.hooks.entryOption.call(options.context, options.entry);
compiler.hooks.afterResolvers.call(compiler);
}
module.exports = WebpackOptionsApply;
这部分需要特别点出两个钩子,entryOption
和afterResolvers
分别表示入口配置和路径解析,当这两部分工作处理完成之后,就可以真正开始最重要的编译构建阶段。
webpack构建流程中关键节点钩子
下面是本次分享主题最干货的部分,重点看这里!重点看这里!重点看这里!
提前剧透一下后面几章讲要分享的内容,该流程图是笔者借鉴网课的基础上修改得到的,里面的每个关键节点都是构建过程中的钩子,下一张将介绍从run->make->buildModule->normal-module-loader->program的过程,也是本次分享里最重要的一部分,webpack的核心构建过程。