.21-浅析webpack源码之事件流this-compilation

  上一节生成Compilation实例后,添加了一些属性,随后触发this-compilation事件流,如下:

Compiler.prototype.newCompilation = (params) => {
    // new Compilation()
    const compilation = this.createCompilation();
    compilation.fileTimestamps = this.fileTimestamps;
    compilation.contextTimestamps = this.contextTimestamps;
    compilation.name = this.name;
    compilation.records = this.records;
    compilation.compilationDependencies = params.compilationDependencies;
    // Go!
    this.applyPlugins("this-compilation", compilation, params);
    this.applyPlugins("compilation", compilation, params);
    return compilation;
}

  事件流的名字this-compilation我想了半天也不懂啥意思,从其内容来看其实也只算是一个预编译,叫pre-compilation似乎更好。

  总之先不管那么多,继续跑流程,流程图如下:

  this-compilation事件流的plugin来源有两个地方,分别是:

// JsonpTemplatePlugin
class JsonpTemplatePlugin {
    apply(compiler) {
        compiler.plugin("this-compilation", (compilation) => {
            compilation.mainTemplate.apply(new JsonpMainTemplatePlugin());
            compilation.chunkTemplate.apply(new JsonpChunkTemplatePlugin());
            compilation.hotUpdateChunkTemplate.apply(new JsonpHotUpdateChunkTemplatePlugin());
        });
    }
}
// CachePlugin
compiler.plugin("this-compilation", compilation => {
    // TODO remove notCacheable for webpack 4
    if (!compilation.notCacheable) {
        compilation.cache = cache;
        compilation.plugin("child-compiler", (childCompiler, compilerName, compilerIndex) => { /**/ });
    } else if (this.watching) {
        compilation.warnings.push(
            new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
        );
    }
});

  两者都出现在WebpackOptionsApply模块中,依次看具体内容。

JsonpTemplatePlugin

  这里依次在上节中提到的Compilation几个属性上加载插件(Tapable),首先是:

compilation.mainTemplate.apply(new JsonpMainTemplatePlugin());

  该插件源码整理如下:

"use strict";
const Template = require("./Template");
class JsonpMainTemplatePlugin {
    apply(mainTemplate) {
        // this.plugin("startup", (source, chunk, hash) => { /**/ });
        // this.plugin("render", (bootstrapSource, chunk, hash, moduleTemplate, dependencyTemplates) => { /**/ });
        // this.plugin("local-vars", (source, chunk, hash) => { /**/ });
        // this.plugin("require", (source, chunk, hash) => { /**/ });
        // this.plugin("module-obj", (source, chunk, hash, varModuleId) => { /**/ });
        // this.plugin("require-extensions", (source, chunk, hash) => { /**/ });
        mainTemplate.plugin("local-vars", function(source, chunk) { /**/ });
        mainTemplate.plugin("jsonp-script", function(_, chunk, hash) { /**/ });
        mainTemplate.plugin("require-ensure", function(_, chunk, hash) { /**/ });
        mainTemplate.plugin("require-extensions", function(source, chunk) { /**/ });
        mainTemplate.plugin("bootstrap", function(source, chunk, hash) { /**/ });
        mainTemplate.plugin("hot-bootstrap", function(source, chunk, hash) { /**/ });
        mainTemplate.plugin("hash", function(hash) { /**/ });
    }
}
module.exports = JsonpMainTemplatePlugin;

  可见,这里只是注入对应的事件流,这里我在注释同时给出了该属性初始化时的plugin,可以对比一下,只有local-vars是重复的。

  既然没有任何的apply操作,就暂时先跳过。

  然后是第二个:

compilation.chunkTemplate.apply(new JsonpChunkTemplatePlugin());

  源码如下:

"use strict";
const ConcatSource = require("webpack-sources").ConcatSource;
class JsonpChunkTemplatePlugin {
    apply(chunkTemplate) {
        chunkTemplate.plugin("render", function(modules, chunk) { /**/ });
        chunkTemplate.plugin("hash", function(hash) { /**/ });
    }
}
module.exports = JsonpChunkTemplatePlugin;

  同样只是注入事件流,该属性在初始化没有做操作,所有事件流只有这两。

  第三个:

compilation.hotUpdateChunkTemplate.apply(new JsonpHotUpdateChunkTemplatePlugin());
"use strict";
const ConcatSource = require("webpack-sources").ConcatSource;
class JsonpHotUpdateChunkTemplatePlugin {
    apply(hotUpdateChunkTemplate) {
        hotUpdateChunkTemplate.plugin("render", function(modulesSource, modules, removedModules, hash, id) { /**/ });
        hotUpdateChunkTemplate.plugin("hash", function(hash) { /**/ });
    }
}
module.exports = JsonpHotUpdateChunkTemplatePlugin;

  与上面那个类似。

  该模块注入完结。

CachePlugin

  该插件注入了多个事件流,直接上与this-compilation事件流相关的代码:

compiler.plugin("this-compilation", compilation => {
    // TODO remove notCacheable for webpack 4
    // 这个属性我从头到尾找不到哪出现的
    // 反正注释说webpack4会将其移除
    if (!compilation.notCacheable) {
        // cache => {}
        compilation.cache = cache;
        // 注入事件流
        compilation.plugin("child-compiler", (childCompiler, compilerName, compilerIndex) => { /**/ });
    }
    // 不可能到达的else
    else if (this.watching) {
        compilation.warnings.push(
            new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
        );
    }
});

  果然是只是注入事件流,这里的notCacheable不知道在哪定义的,也不知道如何修改。

  

  总之this-compilation也并不是编译,只是为一些辅助模块注入事件流。

原文地址:https://www.cnblogs.com/QH-Jimmy/p/8125655.html