乐趣区

关于javascript: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 是如何应用配置中的 entry 属性,获取到 modulefactory,下一篇将介绍 reslove 过程。

退出移动版