compilation实例化
compilation对象
class Compilation {
constructor(compiler, params) {
// ....
this.hooks = Object.freeze({ /**/ })
this.mainTemplate = new MainTemplate(this.outputOptions, this);
this.chunkTemplate = new ChunkTemplate(this.outputOptions, this);
this.runtimeTemplate = new RuntimeTemplate(
this,
this.outputOptions,
this.requestShortener
);
this.moduleTemplates = {
javascript: new ModuleTemplate(this.runtimeTemplate, this)
};
this.processDependenciesQueue = new AsyncQueue({
name: "processDependencies",
parallelism: options.parallelism || 100,
processor: this._processModuleDependencies.bind(this)
});
this.addModuleQueue = new AsyncQueue({
name: "addModule",
parent: this.processDependenciesQueue,
getKey: module => module.identifier(),
processor: this._addModule.bind(this)
});
this.factorizeQueue = new AsyncQueue({
name: "factorize",
parent: this.addModuleQueue,
processor: this._factorizeModule.bind(this)
});
this.buildQueue = new AsyncQueue({
name: "build",
parent: this.factorizeQueue,
processor: this._buildModule.bind(this)
});
}
getCache(name) {
return this.compiler.getCache(name);
}
addModule(module, callback) {
this.addModuleQueue.add(module, callback);
}
_addModule(module, callback) {}
buildModule(module, callback) {
this.buildQueue.add(module, callback);
}
_buildModule(module, callback) {}
processModuleDependencies(module, callback) {}
handleModuleCreation(
{
factory,
dependencies,
originModule,
contextInfo,
context,
recursive = true,
connectOrigin = recursive
},
callback
) {}
_handleModuleBuildAndDependencies(originModule, module, recursive, callback) {
this.processDependenciesQueue.add(module, callback);
}
_factorizeModule(
{
currentProfile,
factory,
dependencies,
originModule,
factoryResult,
contextInfo,
context
},
callback
) {}
addModuleChain(context, dependency, callback) {
return this.addModuleTree({ context, dependency }, callback);
}
addModuleTree({ context, dependency, contextInfo }, callback) { }
addEntry(context, entry, optionsOrName, callback) {
// TODO webpack 6 remove
const options =
typeof optionsOrName === "object"
? optionsOrName
: { name: optionsOrName };
this._addEntryItem(context, entry, "dependencies", options, callback);
}
_addEntryItem(context, entry, target, options, callback) {}
finish(callback) {}
seal(callback) {}
createModuleHashes() {}
emitAsset(file, source, assetInfo = {}) {}
}
compilation对象实例化compilation类型,实例化的调用是由前面的compiler.newCompilation()方法完成
compilation对象是webpack构建编译具体过程的实施者
compilation类型
构造函数的参数
- compiler: Compiler类型实例,床罩当前compilation的compiler对象
- params: 创建compilation所需的参数对象。
构造函数
this.hooks
这个hooks包含了addEntry,finishModule,optimize, optimizeModule, seal, unseal, beforeChunk, afterChunk等钩子
this.mainTemplate
ompilation.mainTemplate是用来渲染入口chunk的模板,compilation.mainTemplate的作用是根据chunk生成最终的文件
- 模板hash更新
- 模板渲染chunk
- 生成文件。
this.chunktemplate
ompilation.chunkTemplate用于动态引入非入口的chunk的渲染模板
webpack构建过程中会将输入的模板分割为多个代码块chunks, 每个chunk都是一个独立的代码块,包含了相关的模板代码和运行时代码。compliation.chunkTemplate提供了一种方式来定义或者修改代码块的生成相关逻辑
this.runtimeTemplate
在webpack中,compiltion.runtimeTemplate用于生成运行时模板,运行时模板是用于生成最终输出文件的一部分。
所谓的webpack运行时就是runtime代码。webpack内部实现的模块加载,导出,异步加载等用于组织webpack构建的bundle和chunk正确执行的代码。
- __webpack_require__方法webpack运行时的主要方法,用于创建并缓存module对象,执行这个module中的代码
function __webpack_require__(moduleId) {}
- _webpack_require.e方法用于加载额外的chunk的函数,比如按需加载的chunk,这里面就会创建script标签然后去加载代码的具体逻辑
__webpack_require__.e = function requireEnsure(chunkId) {};
- _webpack_require.m属性暴露这个runtime接受到的modules对象
__webpack_require_.m = modules
- _webpack_require.d方法,在模块对象exports对象上添加属性,以getter的形式定义导出
__webpack_require_.m = function(exports, name, getter) {}
- _webpack_require.r静态方法,在静态对象中添加_esModule属性,用于标识这个模块是es6模块
__webpack_require_.r = function(exports) {}
this.moduleTemplate
webpack中,moduletemplate是用来渲染chunk的module的模块,用来与mainTemplate和chunktemplate联用,在实例化compilation对象时被创建,分别对应chunk,动态引入的非入口的chunk以及chunk中的module的渲染模板。
模块构建四队列
webpack的模块创建,依赖模块的解析创建以及编译工作依靠下面的四个队列来实现。
this.processDependenciesQueue
this.processDependenciesQueue = new AsyncQueue({
name: 'processDependencies',
parallelism: options.parallelism || 100,
processor: this._processModuleDependencies.bind(this)
})
该队列是webpack处理模块创建以及依赖解析的四个队列的最顶层的队列,就是说,无论是后面的factorizeQueue
, addModuleQueue
, buildQueue
那个队列都会触发processDependenciesQueue
。
该队列中的processor为this._processModuleDependencies方法,接受factorizeQueue的处理结果,将factorize创建的模块加入到队列,随即被processDependenciesQueue队列里的processor._processModuleDependencies小号,用于处理构建中当前模块的依赖模块的构建
this.addModuleQueue
this.addModuleQueue = new AsyncQueue({
name: 'addModule',
parent: this.processDependenciesQueue,
getKey: module => module/identifier(),
processor: this._addmodule.bind(this)
})
该process方法的主要作用是根据module.identifier判断并尝试缓存,然后将module加入到this.modules和this._modules中,然后去执行addModuleQueue时传入的回调函数,建立originModule.setResolveModule, moduleGraph.setIssuerIfUnset以及依赖的关系,也就是compilation.moduleGraph,最后将依赖添加到this.processDependenciesQueue中进行解析。
this.factorizeQueue
factorizeQueue工厂队列,其processor为this._factorizeModule方法,内部调用的factory.create也就是NormalModuleFactory.create方法创建的模板实例。
this.factorizeQueue = new AsyncQueue({
name: "factorize",
parent: this.addModuleQueue,
processor: this._factorizeModule.bind(this)
});
this.buildQueue
buileQueue用于处理模块构建的队列,该队列的processor是this._buildModule方法, 该方法内部主要用于调用各个module.build方法进行模块的构建工作, 在构建完成之后将所得内容加入到this.processDependenciesQueue队列,这样就完成了整个队列的构建过程
this.buildQueue = new AsyncQueue({
name: "build",
parent: this.factorizeQueue,
processor: this._buildModule.bind(this)
});