| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- */
- "use strict";
- const RuntimeGlobals = require("../RuntimeGlobals");
- const RuntimeModule = require("../RuntimeModule");
- const Template = require("../Template");
- const {
- generateJavascriptHMR
- } = require("../hmr/JavascriptHotModuleReplacementHelper");
- const { chunkHasJs } = require("../javascript/JavascriptModulesPlugin");
- const { getInitialChunkIds } = require("../javascript/StartupHelpers");
- const { renderBaseUri } = require("../runtime/baseUri");
- const compileBooleanMatcher = require("../util/compileBooleanMatcher");
- /** @import Chunk from "../Chunk" */
- /** @import ChunkGraph from "../ChunkGraph" */
- /** @import Compilation from "../Compilation" */
- /** @import RuntimeTemplate from "../RuntimeTemplate" */
- /** @import { ReadOnlyRuntimeRequirements } from "../Module" */
- class RequireChunkLoadingRuntimeModule extends RuntimeModule {
- /**
- * Creates an instance of RequireChunkLoadingRuntimeModule.
- * @param {ReadOnlyRuntimeRequirements} runtimeRequirements runtime requirements
- */
- constructor(runtimeRequirements) {
- super("require chunk loading", RuntimeModule.STAGE_ATTACH);
- /** @type {ReadOnlyRuntimeRequirements} */
- this.runtimeRequirements = runtimeRequirements;
- }
- /**
- * Returns generated code.
- * @private
- * @param {Chunk} chunk chunk
- * @param {string} rootOutputDir root output directory
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {string} generated code
- */
- _generateBaseUri(chunk, rootOutputDir, runtimeTemplate) {
- const options = chunk.getEntryOptions();
- return renderBaseUri(
- options ? options.baseUri : undefined,
- `require(${runtimeTemplate.renderNodePrefixForCoreModule("url")}).pathToFileURL(${
- rootOutputDir !== "./"
- ? `__dirname + ${JSON.stringify(`/${rootOutputDir}`)}`
- : "__filename"
- })`
- );
- }
- /**
- * Generates runtime code for this runtime module.
- * @returns {string | null} runtime code
- */
- generate() {
- const compilation = /** @type {Compilation} */ (this.compilation);
- const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
- const chunk = /** @type {Chunk} */ (this.chunk);
- const { runtimeTemplate } = compilation;
- const fn = RuntimeGlobals.ensureChunkHandlers;
- const withBaseURI = this.runtimeRequirements.has(RuntimeGlobals.baseURI);
- const withExternalInstallChunk = this.runtimeRequirements.has(
- RuntimeGlobals.externalInstallChunk
- );
- const withOnChunkLoad = this.runtimeRequirements.has(
- RuntimeGlobals.onChunksLoaded
- );
- const withLoading = this.runtimeRequirements.has(
- RuntimeGlobals.ensureChunkHandlers
- );
- const withHmr = this.runtimeRequirements.has(
- RuntimeGlobals.hmrDownloadUpdateHandlers
- );
- const withHmrManifest = this.runtimeRequirements.has(
- RuntimeGlobals.hmrDownloadManifest
- );
- const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
- const hasJsMatcher = compileBooleanMatcher(conditionMap);
- const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
- const rootOutputDir = runtimeTemplate.chunkRootOutputDir(chunk, true);
- const stateExpression = withHmr
- ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_require`
- : undefined;
- const cst = runtimeTemplate.renderConst();
- const installedChunksObject = `{\n${Template.indent(
- Array.from(initialChunkIds, (id) => `${JSON.stringify(id)}: 1`).join(
- ",\n"
- )
- )}\n}`;
- // Every part below that reads the table. A chunk asking only for `.b` gets this
- // module for the base uri alone, and then has nothing to look up.
- const withInstalledChunks =
- withOnChunkLoad || withLoading || withExternalInstallChunk || withHmr;
- return Template.asString([
- withBaseURI
- ? this._generateBaseUri(chunk, rootOutputDir, runtimeTemplate)
- : "// no baseURI",
- "",
- withInstalledChunks
- ? Template.asString([
- "// object to store loaded chunks",
- '// "1" means "loaded", otherwise not loaded yet',
- `${cst} installedChunks = ${
- stateExpression
- ? runtimeTemplate.assignOr(
- stateExpression,
- installedChunksObject
- )
- : installedChunksObject
- };`
- ])
- : "// no installed chunks",
- "",
- withOnChunkLoad
- ? `${
- RuntimeGlobals.onChunksLoaded
- }.require = ${runtimeTemplate.returningFunction(
- "installedChunks[chunkId]",
- "chunkId"
- )};`
- : "// no on chunks loaded",
- "",
- withLoading || withExternalInstallChunk
- ? `${cst} installChunk = ${runtimeTemplate.basicFunction("chunk", [
- `${cst} moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;`,
- "for(var moduleId in moreModules) {",
- Template.indent([
- `if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
- Template.indent([
- `${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
- ]),
- "}"
- ]),
- "}",
- `if(runtime) runtime(${RuntimeGlobals.require});`,
- "for(var i = 0; i < chunkIds.length; i++)",
- Template.indent("installedChunks[chunkIds[i]] = 1;"),
- withOnChunkLoad ? `${RuntimeGlobals.onChunksLoaded}();` : ""
- ])};`
- : "// no chunk install function needed",
- "",
- withLoading
- ? Template.asString([
- "// require() chunk loading for javascript",
- `${fn}.require = ${runtimeTemplate.basicFunction(
- "chunkId, promises",
- hasJsMatcher !== false
- ? [
- '// "1" is the signal for "already loaded"',
- "if(!installedChunks[chunkId]) {",
- Template.indent([
- hasJsMatcher === true
- ? "if(true) { // all chunks have JS"
- : `if(${hasJsMatcher("chunkId")}) {`,
- Template.indent([
- // The require function loads and runs a chunk. When the chunk is being run,
- // it can call __webpack_require__.C to directly complete installed.
- `${cst} installedChunk = require(${JSON.stringify(
- rootOutputDir
- )} + ${
- RuntimeGlobals.getChunkScriptFilename
- }(chunkId));`,
- "if (!installedChunks[chunkId]) {",
- Template.indent(["installChunk(installedChunk);"]),
- "}"
- ]),
- "} else installedChunks[chunkId] = 1;",
- ""
- ]),
- "}"
- ]
- : "installedChunks[chunkId] = 1;"
- )};`
- ])
- : "// no chunk loading",
- "",
- withExternalInstallChunk
- ? Template.asString([
- `module.exports = ${RuntimeGlobals.require};`,
- `${RuntimeGlobals.externalInstallChunk} = installChunk;`
- ])
- : "// no external install chunk",
- "",
- withHmr
- ? Template.asString([
- "function loadUpdateChunk(chunkId, updatedModulesList) {",
- Template.indent([
- `${cst} update = require(${JSON.stringify(rootOutputDir)} + ${
- RuntimeGlobals.getChunkUpdateScriptFilename
- }(chunkId));`,
- `${cst} updatedModules = update.modules;`,
- `${cst} runtime = update.runtime;`,
- "for(var moduleId in updatedModules) {",
- Template.indent([
- `if(${RuntimeGlobals.hasOwnProperty}(updatedModules, moduleId)) {`,
- Template.indent([
- "currentUpdate[moduleId] = updatedModules[moduleId];",
- `${runtimeTemplate.optionalChaining("updatedModulesList", "push(moduleId)")};`
- ]),
- "}"
- ]),
- "}",
- "if(runtime) currentUpdateRuntime.push(runtime);"
- ]),
- "}",
- "",
- generateJavascriptHMR("require")
- ])
- : "// no HMR",
- "",
- withHmrManifest
- ? Template.asString([
- `${RuntimeGlobals.hmrDownloadManifest} = function() {`,
- Template.indent([
- "return Promise.resolve().then(function() {",
- Template.indent([
- `return require(${JSON.stringify(rootOutputDir)} + ${
- RuntimeGlobals.getUpdateManifestFilename
- }());`
- ]),
- `}).catch(${runtimeTemplate.basicFunction("err", [
- "if(['MODULE_NOT_FOUND', 'ENOENT'].includes(err.code)) return;",
- "throw err;"
- ])});`
- ]),
- "}"
- ])
- : "// no HMR manifest"
- ]);
- }
- }
- module.exports = RequireChunkLoadingRuntimeModule;
|