webpack/lib/container/OverridablesRuntimeModule.js

154 lines
4.6 KiB
JavaScript

/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const RuntimeModule = require("../RuntimeModule");
const Template = require("../Template");
/** @typedef {import("./OverridableModule")} OverridableModule */
class OverridablesRuntimeModule extends RuntimeModule {
constructor(runtimeRequirements) {
super("overridables");
this._runtimeRequirements = runtimeRequirements;
}
/**
* @returns {string} runtime code
*/
generate() {
const {
runtimeTemplate,
moduleGraph,
chunkGraph,
codeGenerationResults
} = this.compilation;
const chunkToOverridableMapping = {};
const idToNameMapping = {};
const overridableToFallbackMapping = new Map();
const initialOverridables = {};
const asyncChunks = this.chunk.getAllAsyncChunks();
for (const chunk of asyncChunks) {
const modules = chunkGraph.getChunkModulesIterableBySourceType(
chunk,
"overridable"
);
if (!modules) continue;
const overridables = (chunkToOverridableMapping[chunk.id] = []);
for (const m of modules) {
const module = /** @type {OverridableModule} */ (m);
const name = module.options.name;
const id = chunkGraph.getModuleId(module);
overridables.push(id);
idToNameMapping[id] = name;
const source = codeGenerationResults
.get(module)
.sources.get("overridable");
overridableToFallbackMapping.set(id, source.source());
}
}
for (const chunk of this.chunk.getAllReferencedChunks()) {
if (asyncChunks.has(chunk)) continue;
const modules = chunkGraph.getChunkModulesIterableBySourceType(
chunk,
"overridable"
);
if (!modules) continue;
for (const m of modules) {
const module = /** @type {OverridableModule} */ (m);
const name = module.options.name;
const id = chunkGraph.getModuleId(module);
idToNameMapping[id] = name;
const fallbackModule = moduleGraph.getModule(
module.blocks[0].dependencies[0]
);
const fallbackId = chunkGraph.getModuleId(fallbackModule);
initialOverridables[id] = fallbackId;
}
}
return Template.asString([
`${RuntimeGlobals.overrides} = {};`,
"var installedModules = {};",
`var idToNameMapping = ${JSON.stringify(idToNameMapping, null, "\t")};`,
Object.keys(initialOverridables).length
? Template.asString([
`var initialOverridables = ${JSON.stringify(
initialOverridables,
null,
"\t"
)};`,
`for(var id in initialOverridables) if(${
RuntimeGlobals.hasOwnProperty
}(initialOverridables, id)) __webpack_modules__[id] = (${runtimeTemplate.returningFunction(
`${runtimeTemplate.basicFunction("module", [
"// Handle case when module is used sync",
"installedModules[id] = 0;",
`var override = ${RuntimeGlobals.overrides}[idToNameMapping[id]];`,
"module.exports = override ? override()() : __webpack_require__(initialOverridables[id]);"
])}`,
"id"
)})(id);`
])
: "// no overridables in initial chunks",
this._runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers)
? Template.asString([
`var chunkMapping = ${JSON.stringify(
chunkToOverridableMapping,
null,
"\t"
)};`,
"var fallbackMapping = {",
Template.indent(
Array.from(
overridableToFallbackMapping,
([id, source]) =>
`${JSON.stringify(id)}: ${runtimeTemplate.basicFunction(
"",
source
)}`
).join(",\n")
),
"};",
`${
RuntimeGlobals.ensureChunkHandlers
}.overridables = ${runtimeTemplate.basicFunction(
"chunkId, promises",
[
`if(${RuntimeGlobals.hasOwnProperty}(chunkMapping, chunkId)) {`,
Template.indent([
`chunkMapping[chunkId].forEach(${runtimeTemplate.basicFunction(
"id",
[
`promises.push(${
RuntimeGlobals.hasOwnProperty
}(installedModules, id) ? installedModules[id] : installedModules[id] = Promise.resolve((${
RuntimeGlobals.overrides
}[idToNameMapping[id]] || fallbackMapping[id])()).then(${runtimeTemplate.basicFunction(
"factory",
[
"installedModules[id] = 0;",
`__webpack_modules__[id] = ${runtimeTemplate.basicFunction(
"module",
["module.exports = factory();"]
)}`
]
)}))`
]
)});`
]),
"}"
]
)}`
])
: "// no chunk loading of overridables"
]);
}
}
module.exports = OverridablesRuntimeModule;