webpack源码解析---compilation实例化

发布于:2024-07-07 ⋅ 阅读:(126) ⋅ 点赞:(0)

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类型

构造函数的参数

  1. compiler: Compiler类型实例,床罩当前compilation的compiler对象
  2. params: 创建compilation所需的参数对象。

构造函数

this.hooks

这个hooks包含了addEntry,finishModule,optimize, optimizeModule, seal, unseal, beforeChunk, afterChunk等钩子

this.mainTemplate

ompilation.mainTemplate是用来渲染入口chunk的模板,compilation.mainTemplate的作用是根据chunk生成最终的文件

  1. 模板hash更新
  2. 模板渲染chunk
  3. 生成文件。
this.chunktemplate

ompilation.chunkTemplate用于动态引入非入口的chunk的渲染模板
webpack构建过程中会将输入的模板分割为多个代码块chunks, 每个chunk都是一个独立的代码块,包含了相关的模板代码和运行时代码。compliation.chunkTemplate提供了一种方式来定义或者修改代码块的生成相关逻辑

this.runtimeTemplate

在webpack中,compiltion.runtimeTemplate用于生成运行时模板,运行时模板是用于生成最终输出文件的一部分。
所谓的webpack运行时就是runtime代码。webpack内部实现的模块加载,导出,异步加载等用于组织webpack构建的bundle和chunk正确执行的代码。

  1. __webpack_require__方法webpack运行时的主要方法,用于创建并缓存module对象,执行这个module中的代码
function __webpack_require__(moduleId) {}
  1. _webpack_require.e方法用于加载额外的chunk的函数,比如按需加载的chunk,这里面就会创建script标签然后去加载代码的具体逻辑
__webpack_require__.e = function requireEnsure(chunkId) {};
  1. _webpack_require.m属性暴露这个runtime接受到的modules对象
__webpack_require_.m = modules
  1. _webpack_require.d方法,在模块对象exports对象上添加属性,以getter的形式定义导出
__webpack_require_.m = function(exports, name, getter) {}
  1. _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)
});