1.Compiler
// 1. 执行run方法开始编译
run() {
// 开始编译 编译完成了执行onCompiled(stats)
this.compiler(onCompiled)
}
// 编译
compiler(callback) {
// 创建参数
// const params = this.newCompilationParams();
const params = {
// 普通模块工厂
normalModuleFactory: this.createNormalModuleFactory(),
// 上下文模块工厂
contextModuleFactory: this.createContextModuleFactory(),
// 依赖的集合
compilationDependencies: new Set(),
}
// 创建compilation对象 params中有普通模块工厂的
const compilation = this.newCompilation(params);
// 执行make构建 执行单入口插件中注册的钩子
this.hooks.make(compilation, callback)
}
2. SingleEntryPlugin
// class SingleEntryPlugin 在webpack执行过程中会注册插件
apply(compiler) {
compiler.hooks.compilation.tap(
"SingleEntryPlugin",
(compilation, { normalModuleFactory }) => {
// 给compilation的dependencyFactories属性添加属性
compilation.dependencyFactories.set(
SingleEntryDependency,
normalModuleFactory
);
}
);
// compiler中执行make的时候就会执行这个插件
compiler.hooks.make.tapAsync(
"SingleEntryPlugin",
(compilation, callback) => {
console.log("SingleEntryPlugin 从此入口文件开始编译");
// entry是入口文件 name是代码块的名称 context上下文绝对路径
const { entry, name, context } = this;
// 给entry添加了一些属性
const dep = SingleEntryPlugin.createDependency(entry, name);
// 编译入口文件和他的依赖 这里的dep简单看就是entry
// {loc: {name: 'main'}, module: null, request:'./src/index.js', single entry }
compilation.addEntry(context, dep, name, callback);
}
);
}
static createDependency(entry, name) {
// 继承ModuleDependency 继承Dependency
const dep = new SingleEntryDependency(entry);
dep.loc = { name };
return dep;
}
3.Compilation
class Compilation extends Tapable {
constructor(compiler) {
// 在SingleEntryPlugin的compilation钩子会给变量赋值 不同的文件会对应不同的模块工厂
this.dependencyFactories = new Map();
}
// 执行make之后会执行单入口插件的hook执行addEntry() 开始编译一个入口
addEntry() {
// 增加模块链
this._addModuleChain(
context,
entry,
(module) => this.entries.push(module),
callback
);
}
_addModuleChain(context, dependency, onModule, callback) {
//dep = new new SingleEntryDependency() singleEntryDependency
const Dep = dependency.constructor;
// 拿到普通模块工厂 normalModuleFactory
const moduleFactory = this.dependencyFactories.get(Dep);
// 调用create方法创建模块
moduleFactory.create({}, (err, module) => {
// 调用module的build方法开始构建
this.buildModule(module, false, null, null, (err) => {});
});
}
}
4. NormalModuleFactory
// 普通模块工厂 如何产生normalModule的
// 简单理解为 create() {return new NormalModule()}
// NormalModuleFactory只是做了一些其他的处理
class NormalModuleFactory extends Tapable {
constructor(context, resolverFactory, options) {
// 注册factory钩子 触发返回一个function
this.hooks.factory.tap("NormalModuleFactory", () => (result, callback) => {
let resolver = this.hooks.resolver.call(null);
// 执行resolver处理loader相关的逻辑
resolver(result, (err, data) => {
this.hooks.afterResolve.callAsync(data, (err, result) => {
// 创建模块 NormalModule
let createdModule = this.hooks.createModule.call(result);
// 普通模块
if (!createdModule) createdModule = new NormalModule(result);
createdModule = this.hooks.module.call(createdModule, result);
// 我们的到的模块就普通模块 给create方法
return callback(null, createdModule);
});
});
});
// 注册resolver钩子 会处理一些loader 也会返回一个函数 给factory执行
this.hooks.factory.tap("NormalModuleFactory", () => (result, callback) => {
// loader的处理
callback(null, {});
});
}
// create方法 普通模块创建模块
create(data, callback) {
// 这些参数都会给 factory 执行 factory 的时候会创建 NormalModule 普通模块
const dependencies = data.dependencies;
const context = data.context || this.context;
const resolveOptions = data.resolveOptions || {};
const request = dependencies[0].request; // './src/index.js'
const contextInfo = data.contextInfo || {};
this.hooks.beforeResolve.callAsync({}, (err, result) => {
const factory = this.hooks.factory.call(null);
factory(result, (err, module) => {
// 这里拿到的module就是factory中callback中的createdModule
// 这个module也是执行create返回的module
// 之后再调用module.build方法开始构建
callback(null, module);
});
});
}
}
5.demo
// 简化下上面的逻辑
// 在factory中会执行resolver方法 处理loader
function resolver(data, callback) {
console.log("resolve", data);
callback(null, {
context: "context",
request: "./src/index.js",
});
}
// 注册的factory钩子 执行的时候会返回一个函数
function factory(result, callback) {
resolver(result, (err, data) => {
console.log("resolver", data);
createdModule = new NormalModule(result);
callback(null, createdModule);
});
}
// 一些参数
let result = {
contextInfo: "contextInfo",
resolveOptions: "resolveOptions",
context: "context",
request: "request",
dependencies: "dependencies",
};
// 在create中会执行factory方法
factory(result, (err, module) => {
// 这里就可以拿到NormalModule
console.log("factory", module);
});
6. NormalModule
class NormalModule extends Module {
// 调用模块的build方法开始编译
build(options, compilation, resolver, fs, callback) {
return this.doBuild(options, compilation, resolver, fs, (err) => {
console.log("build");
});
}
}
7.总结
在compiler中执行compiler
==> 创建params 普通模块工厂 normalModuleFactory
==> 创建compilation对象 里面有一个 dependencyFactories 来记录不同模块的工厂函数
==> 创建过程中会触发 this.hooks.compilation.call(compilation, params)
==> 执行SingleEntryPlugin中对应的钩子 记录SingleEntryDependency: normalModuleFactory
==> 执行make ==> 执行SingleEntryPlugin中的钩子
==> 处理entry包装为SingleEntryDependency ==> compilation.addEntry()
=> addEntry开始编译一个新的入口
==> addModuleChain()增加模块链
==> 从dependencyFactories中找到普通模块工厂
==> 调用moduleFactory.create()方法创建
==> create()执行factory 得到module = new NormalModule() 普通模块
==> 执行模块的build方法(NormalModule.build)开始构建模块
==> afterBuild 递归处理依赖
发表评论
还没有评论,快来抢沙发吧!