webpack源码-打包资源输出到本地

webpack收集完依赖是怎么打包资源的呢?

入口compiler.js:

this.applyPluginsParallel("make", compilation, err => {
    if(err) return callback(err);
    compilation.finish();
    compilation.seal(callback);
});

 

执行seal方法,createChunkAssets方法(compilation.js)
createChunkAssets方法的时候做如下判断:

if(chunk.hasRuntime()) {
   source = this.mainTemplate.render(this.hash, chunk, this.moduleTemplate, this.dependencyTemplates);
} else {        
    source = this.chunkTemplate.render(chunk, this.moduleTemplate, this.dependencyTemplates);
}

 

根据是否是entrypoints,进行资源打包(chunk.js)。

上面的mainTemplate.render方法:

render(hash, chunk, moduleTemplate, dependencyTemplates) {
    const buf = [];
    buf.push(this.applyPluginsWaterfall("bootstrap", "", chunk, hash, moduleTemplate, dependencyTemplates));
    buf.push(this.applyPluginsWaterfall("local-vars", "", chunk, hash));
    buf.push("");
    buf.push("// The require function");
    buf.push(`function ${this.requireFn}(moduleId) {`);
    buf.push(this.indent(this.applyPluginsWaterfall("require", "", chunk, hash)));
    buf.push("}");
    buf.push("");
    buf.push(this.asString(this.applyPluginsWaterfall("require-extensions", "", chunk, hash)));
    buf.push("");
    buf.push(this.asString(this.applyPluginsWaterfall("startup", "", chunk, hash)));
    
    let source = this.applyPluginsWaterfall("render", new OriginalSource(this.prefix(buf, " \t") + "\n", `webpack/bootstrap ${hash}`), chunk, hash, moduleTemplate, dependencyTemplates);
    if(chunk.hasEntryModule()) {
        source = this.applyPluginsWaterfall("render-with-entry", source, chunk, hash);
    }
    if(!source) throw new Error("Compiler error: MainTemplate plugin 'render' should return something");
    chunk.rendered = true;
    return new ConcatSource(source, ";");
}

 

buf中保存了webpackBootstrap中的主体代码:
34343

render钩子(MainTemplate.js)

 const source = new ConcatSource();
    source.add("/******/ (function(modules) { // webpackBootstrap\n"); // 添加头部包裹体
    source.add(new PrefixSource("/******/", bootstrapSource)); // 添加bootstrap主体
    source.add("/******/ })\n");  // 结束
    source.add("/*****************************  *******************************************/\n");
    source.add("/******/ (");   
    const modules = this.renderChunkModules(chunk, moduleTemplate, dependencyTemplates, "/******/ ");  // 返回一个concatSource的一个实例,包含了需要打包的所有内容
    source.add(this.applyPluginsWaterfall("modules", modules, chunk, hash, moduleTemplate, dependencyTemplates));
    source.add(")");
    return source;   // 返回一个concatSource实例

 

主要做了两件事:
1.生成webpackBootstrap中的主体代码
2.添加所有的代码到concatSource

最后,执行compiler.run的回调函数 onCompiled(null, compilation)
执行 emitAssets方法

this.outputFileSystem.mkdirp(this.outputFileSystem.join(outputPath, dir), writeOut);// 创建dist目录
const targetPath = this.outputFileSystem.join(outputPath, targetFile);
const source = compilation.assets[file]; // createChunkAssets中有这样的处理this.assets[file] = source;
......
let content = source.source();
if(!Buffer.isBuffer(content)) {
    content = new Buffer(content, "utf8"); 
}
......
this.outputFileSystem.writeFile(targetPath, content, callback);// 输出到本地文件系统

 

至此打包资源,然后就基本结束了。

posted @ 2019-10-28 15:13  空山与新雨  阅读(812)  评论(0编辑  收藏  举报