前言
准备工作做了三遍文章,现在、立刻、马上,我们进入构建流程的分析!
构建入口
这个过程还是在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过程。