webpack
Version:
Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
186 lines (176 loc) • 5.42 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
;
const Parser = require("./Parser");
const Template = require("./Template");
const { ConcatSource } = require("webpack-sources");
const JavascriptGenerator = require("./JavascriptGenerator");
const createHash = require("./util/createHash");
class JavascriptModulesPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"JavascriptModulesPlugin",
(compilation, { normalModuleFactory }) => {
normalModuleFactory.hooks.createParser
.for("javascript/auto")
.tap("JavascriptModulesPlugin", options => {
return new Parser(options, "auto");
});
normalModuleFactory.hooks.createParser
.for("javascript/dynamic")
.tap("JavascriptModulesPlugin", options => {
return new Parser(options, "script");
});
normalModuleFactory.hooks.createParser
.for("javascript/esm")
.tap("JavascriptModulesPlugin", options => {
return new Parser(options, "module");
});
normalModuleFactory.hooks.createGenerator
.for("javascript/auto")
.tap("JavascriptModulesPlugin", () => {
return new JavascriptGenerator();
});
normalModuleFactory.hooks.createGenerator
.for("javascript/dynamic")
.tap("JavascriptModulesPlugin", () => {
return new JavascriptGenerator();
});
normalModuleFactory.hooks.createGenerator
.for("javascript/esm")
.tap("JavascriptModulesPlugin", () => {
return new JavascriptGenerator();
});
compilation.mainTemplate.hooks.renderManifest.tap(
"JavascriptModulesPlugin",
(result, options) => {
const chunk = options.chunk;
const hash = options.hash;
const fullHash = options.fullHash;
const outputOptions = options.outputOptions;
const moduleTemplates = options.moduleTemplates;
const dependencyTemplates = options.dependencyTemplates;
const filenameTemplate =
chunk.filenameTemplate || outputOptions.filename;
const useChunkHash = compilation.mainTemplate.useChunkHash(chunk);
result.push({
render: () =>
compilation.mainTemplate.render(
hash,
chunk,
moduleTemplates.javascript,
dependencyTemplates
),
filenameTemplate,
pathOptions: {
noChunkHash: !useChunkHash,
contentHashType: "javascript",
chunk
},
identifier: `chunk${chunk.id}`,
hash: useChunkHash ? chunk.hash : fullHash
});
return result;
}
);
compilation.mainTemplate.hooks.modules.tap(
"JavascriptModulesPlugin",
(source, chunk, hash, moduleTemplate, dependencyTemplates) => {
return Template.renderChunkModules(
chunk,
m => typeof m.source === "function",
moduleTemplate,
dependencyTemplates,
"/******/ "
);
}
);
compilation.chunkTemplate.hooks.renderManifest.tap(
"JavascriptModulesPlugin",
(result, options) => {
const chunk = options.chunk;
const outputOptions = options.outputOptions;
const moduleTemplates = options.moduleTemplates;
const dependencyTemplates = options.dependencyTemplates;
const filenameTemplate =
chunk.filenameTemplate || outputOptions.chunkFilename;
result.push({
render: () =>
this.renderJavascript(
compilation.chunkTemplate,
chunk,
moduleTemplates.javascript,
dependencyTemplates
),
filenameTemplate,
pathOptions: {
chunk,
contentHashType: "javascript"
},
identifier: `chunk${chunk.id}`,
hash: chunk.hash
});
return result;
}
);
compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
const outputOptions = compilation.outputOptions;
const {
hashSalt,
hashDigest,
hashDigestLength,
hashFunction
} = outputOptions;
const hash = createHash(hashFunction);
if (hashSalt) hash.update(hashSalt);
const template = chunk.hasRuntime()
? compilation.mainTemplate
: compilation.chunkTemplate;
hash.update(`${chunk.id} `);
hash.update(chunk.ids ? chunk.ids.join(",") : "");
template.updateHashForChunk(
hash,
chunk,
compilation.moduleTemplates.javascript,
compilation.dependencyTemplates
);
for (const m of chunk.modulesIterable) {
if (typeof m.source === "function") {
hash.update(m.hash);
}
}
const digest = /** @type {string} */ (hash.digest(hashDigest));
chunk.contentHash.javascript = digest.substr(0, hashDigestLength);
});
}
);
}
renderJavascript(chunkTemplate, chunk, moduleTemplate, dependencyTemplates) {
const moduleSources = Template.renderChunkModules(
chunk,
m => typeof m.source === "function",
moduleTemplate,
dependencyTemplates
);
const core = chunkTemplate.hooks.modules.call(
moduleSources,
chunk,
moduleTemplate,
dependencyTemplates
);
let source = chunkTemplate.hooks.render.call(
core,
chunk,
moduleTemplate,
dependencyTemplates
);
if (chunk.hasEntryModule()) {
source = chunkTemplate.hooks.renderWithEntry.call(source, chunk);
}
chunk.rendered = true;
return new ConcatSource(source, ";");
}
}
module.exports = JavascriptModulesPlugin;