.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也并不是编译,只是为一些辅助模块注入事件流。
老子要日穿V8引擎