| /* |
| MIT License http://www.opensource.org/licenses/mit-license.php |
| Author Tobias Koppers @sokra |
| */ |
| "use strict"; |
| |
| 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; |