compiler.compile
compiler.compile
Compiler.prototype.compile方法总览
class Compiler {
// ...
compile(callback) {
// 调用compiler.newCompilationParams()获取创建compilation实例对象的参数
const params = this.newCompilationParams();
// 传入参数,触发this.hooks.beforeCompile的钩子
this.hooks.beforeCompile.callAsync(params, err => {
// 触发compiler.hooks.compile钩子
this.hooks.compile.call(params);
// 创建compilation对象
const compilation = this.newCompilation(params);
// 触发make的钩子
this.hooks.make.callAsync(compilation, err => {
// 触发finishMake钩子
this.hooks.finishMake.callAsync(compilation, err => {
process.nextTick(() => {
// 触发finish钩子
compilation.finish(err => {
compilation.seal(err => {
this.hooks.afterCompile.callAsync(compilation, err => {
return callback(null, compilation);
});
});
});
});
});
});
});
}
}
compiler.newCompilationParams()方法
class Compiler {
// ...
newCompilationParams() {
const params = {
// 常规模块工厂
normalModuleFactory: this.createNormalModuleFactory(),
// 上下文模块中的工厂类
contextModuleFactory: this.createContextModuleFactory()
};
return params;
}
}
- 普通模块: ESM或者commonjs或者cmd/amd的模块规范产物
- 上下文模块: 当编译的时候无法具体确定某一个模块,可以直接在webpack上引用一整个目录,把目录中的所有模块都打包,然后等到运行的时候去具体某一个的模块, 这种模块叫上下文模块
createNormalModuleFactory方法
class Compiler {
// ...
createNormalModuleFactory() {
const normalModuleFactory = new NormalModuleFactory({});
this.hooks.normalModuleFactory.call(normalModuleFactory);
return normalModuleFactory;
}
}
- 定义 factory/resolve 等 NMF 与模块创建相关生命周期钩子
- 格式化webpack.config.js中定义的loader
- 定义loader和模块的加载解析工作
- 定义模块构建相关工作
createcontextmodulefactory方法和上面的方法类似
compiler.hooks.beforeCompile.call方法
- DllReferencePlugin:DLL引用插件,就是动态链接库的引用库,在beforeCompile阶段尝试manifest.json,就是DLL清单列表
- ProgressPlugin: webpack的构建进度
- lazycompilationPlugin: 用于在webpack beforeCompile中针对一些懒加载的入口进行处理。
compiler.hooks.compile
触发compiler.hooks.compile钩子,有几个插件订阅在这个阶段
- DLLReferencePlugin: 在compiler.hooks.compile阶段根据配置生成externals对象。
- ExternalsPlugin: 处理 external 选项,在该阶段为配置的各个 external 配置 ExternalModuleFactoryPlugin,该插件订阅 NMF 的 factory 阶段为配置的外部模块创建模块,以便这些外部模块可以正常的加入的 webpack runtime 的工作流中
compiler.newCompilation(params)
创建compilation对象,该方法接受前面的params对象
class Compiler {
// ...
newCompilation(params) {
const compilation = this.createCompilation(params);
compilation.name = this.name;
compilation.records = this.records;
this.hooks.thisCompilation.call(compilation, params);
this.hooks.compilation.call(compilation, params);
return compilation;
}
// 创建compilation
createCompilation(params) {
this._cleanupLastCompilation();
return (this._lastCompilation = new Compilation(this, params));
}
}
compilation是webpack中最重要的对象,相当于是处理具体编译相关事宜的对象。包括模块构建,生成moduleGraph,chunkGraph,以及模块,chunk的相关优化的工作
compiler.hooks.make
有了compilation之后,触发compiler.hooks.make钩子,进入了模块构建阶段。webpackoptionsapply.prototype.process方法注册了EntryOptionsApply,EntryPlugin为每个entry注册了EntryPlugin,而EntryPlugin又订阅了compiler.hooks.make钩子
EntryOptionPlugin
EntryOption订阅了compiler.hooks.entryOption钩子,当钩子触发调用EntryOptionPlugin.applyEntryPlugin根据不同的类型的入口应用不同的类型的入口插件
class EntryOptionPlugin {
apply(compiler) {
// 订阅 compiler.hooks.entryOpion 钩子
compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
EntryOptionPlugin.applyEntryOption(compiler, context, entry);
return true;
});
}
static applyEntryOption(compiler, context, entry) {
if (typeof entry === "function") {
// 处理动态入口场景
const DynamicEntryPlugin = require("./DynamicEntryPlugin");
new DynamicEntryPlugin(context, entry).apply(compiler);
} else {
// 初始化 EntryPlugin 插件初始化普通入口
const EntryPlugin = require("./EntryPlugin");
for (const name of Object.keys(entry)) {
const desc = entry[name];
const options = EntryOptionPlugin.entryDescriptionToOptions(
compiler,
name,
desc
);
for (const entry of desc.import) {
new EntryPlugin(context, entry, options).apply(compiler);
}
}
}
}
}
EntryPlugin
class EntryPlugin {
constructor(context, entry, options) {
this.context = context;
this.entry = entry;
this.options = options || "";
}
apply(compiler) {
compiler.hooks.compilation.tap(
"EntryPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
EntryDependency,
normalModuleFactory
);
}
);
const { entry, options, context } = this;
const dep = EntryPlugin.createDependency(entry, options);
compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {
compilation.addEntry(context, dep, options, err => {
callback(err);
});
});
}
}
- 订阅compiler.hooks.compilation钩子,向EntryDependency设置工厂类为normalModuleFactory
- 创建入口依赖并订阅compiler.hooks.make钩子