mirror of https://github.com/webpack/webpack.git
154 lines
4.6 KiB
JavaScript
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;
|