前言
準備工作做了三遍文章,現在、立刻、馬上,我們進入構建流程的分析!
構建入口
這個過程還是在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過程。