前言
筹备工作做了三遍文章,当初、立即、马上,咱们进入构建流程的剖析!
构建入口
这个过程还是在 compiler.compiler
函数里,
// 在这之前 new 了一个 compilation 对象
this.hooks.make.callAsync(compilation, err => {logger.timeEnd("make hook");
if (err) return callback(err);
logger.time("finish make hook");
this.hooks.finishMake.callAsync(compilation, err => {logger.timeEnd("finish make hook");
if (err) return callback(err);
process.nextTick(() => {logger.time("finish compilation");
compilation.finish(err => {logger.timeEnd("finish compilation"); if (err) return callback(err);
logger.time("seal compilation");
compilation.seal(err => {//dosomething});
});
});
});
});
这里触发了 make
钩子注册的回调,还记得我在初始化局部提到的 EntryPlugin
吗?在这里注册了一个钩子回调,触发了 compilation.addEntry
compilation.addEntry(context, dependency, name, callback); // 其中 dependency 为 EntryDependency 实例。
addEntry
addEntry 做了这么几件事:
- 生成 EntryData
- 调用
compilation
钩子addEntry
- 执行 compilation.addModule
addModule
addModule 依据 dep,拿到对应的 moduleFactory, 而后执行 handleModuleCreation
, 把 moduleFactory
和dependency
等数据塞入一个队列factorizeQueue
获取 moduleFactory
const Dep = /** @type {DepConstructor} */ (dependency.constructor);
const moduleFactory = this.dependencyFactories.get(Dep);
this.dependencyFactories
是一个 Map, 那么他是什么时候 set 的呢?答案还是在初始化局部提到的 EntryPlugin
中。
** 塞入队列
获取到依赖和模块的编译办法之后,塞入 factorizeQueue
队列
this.factorizeModule({
currentProfile,
factory,
dependencies,
factoryResult: true,
originModule,
contextInfo,
context
},
() => { // dosomethine})
// Workaround for typescript as it doesn't support function overloading in jsdoc within a class
Compilation.prototype.factorizeModule =
/** @type {{(options: FactorizeModuleOptions & { factoryResult?: false}, callback: ModuleCallback): void;
(options: FactorizeModuleOptions & { factoryResult: true}, callback: ModuleFactoryResultCallback): void;
}} */
(function (options, callback) {this.factorizeQueue.add(options, callback);
}
);
看到这里,有点没有脉络,add 之后在整个 compilation
里没有找到相似于 factorizeQueue.start,factorizeQueue.run 之类的代码。一起去看看factorizeQueue
外部干了啥
factorizeQueue
this.factorizeQueue = new AsyncQueue({
name: "factorize",
parent: this.addModuleQueue,
processor: this._factorizeModule.bind(this)
});
factorizeQueue
是 AsyncQueue
的实例。AsyncQueue
次要是做了一个队列管制。队列长度依据内部传入的 parallelism
来管制,factorizeQueue
没有传,这里默认为 1。
如果条件 ok,在 AsyncQueue
的外部会调用_processor
this._processor(entry.item, (e, r) => {
inCallback = true;
this._handleResult(entry, e, r);
});
这里就调用到_factorizeModule
, 接下来执行factory.create
,开始reslove!
结语
到这里咱们曾经理解到 webpack
是如何应用配置中的 entry
属性,获取到 modulefactory,下一篇将介绍 reslove 过程。