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
中的主体代码:

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);// 输出到本地文件系统
至此打包资源,然后就基本结束了。