webpack|webpack 流程解析(4): 开始构建

前言 准备工作做了三遍文章,现在、立刻、马上,我们进入构建流程的分析!
构建入口 这个过程还是在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, 把 moduleFactorydependency等数据塞入一个队列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.startfactorizeQueue.run 之类的代码。一起去看看factorizeQueue 内部干了啥
factorizeQueue
this.factorizeQueue = new AsyncQueue({ name: "factorize", parent: this.addModuleQueue, processor: this._factorizeModule.bind(this) });

factorizeQueueAsyncQueue 的实例。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|webpack 流程解析(4): 开始构建】到这里我们已经了解到webpack是如何使用配置中的entry属性,获取到modulefactory,下一篇将介绍reslove过程。

    推荐阅读