You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
5.3 KiB
186 lines
5.3 KiB
4 years ago
|
/*
|
||
|
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;
|