ModuleChunkLoadingRuntimeModule.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. */
  4. "use strict";
  5. const { SyncWaterfallHook } = require("tapable");
  6. /** @import Compilation from "../Compilation" */
  7. const RuntimeGlobals = require("../RuntimeGlobals");
  8. const RuntimeModule = require("../RuntimeModule");
  9. const Template = require("../Template");
  10. const {
  11. generateJavascriptHMR
  12. } = require("../hmr/JavascriptHotModuleReplacementHelper");
  13. const { chunkHasJs } = require("../javascript/JavascriptModulesPlugin");
  14. const { getInitialChunkIds } = require("../javascript/StartupHelpers");
  15. const { renderBaseUri } = require("../runtime/baseUri");
  16. const compileBooleanMatcher = require("../util/compileBooleanMatcher");
  17. const createHooksRegistry = require("../util/createHooksRegistry");
  18. const memoize = require("../util/memoize");
  19. const getAPIPlugin = memoize(() => require("../APIPlugin"));
  20. /** @import Chunk from "../Chunk" */
  21. /** @import ChunkGraph from "../ChunkGraph" */
  22. /** @import { ReadOnlyRuntimeRequirements } from "../Module" */
  23. const createCompilationHooks = () => ({
  24. /**
  25. * @type {SyncWaterfallHook<[string, Chunk]>}
  26. * @since 5.41.0
  27. */
  28. linkPreload: new SyncWaterfallHook(["source", "chunk"]),
  29. /**
  30. * @type {SyncWaterfallHook<[string, Chunk]>}
  31. * @since 5.41.0
  32. */
  33. linkPrefetch: new SyncWaterfallHook(["source", "chunk"])
  34. });
  35. /**
  36. * @typedef {ReturnType<typeof createCompilationHooks>} JsonpCompilationPluginHooks
  37. */
  38. class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
  39. /**
  40. * Creates an instance of ModuleChunkLoadingRuntimeModule.
  41. * @param {ReadOnlyRuntimeRequirements} runtimeRequirements runtime requirements
  42. */
  43. constructor(runtimeRequirements) {
  44. super("import chunk loading", RuntimeModule.STAGE_ATTACH);
  45. /** @type {ReadOnlyRuntimeRequirements} */
  46. this._runtimeRequirements = runtimeRequirements;
  47. }
  48. /**
  49. * Returns generated code.
  50. * @private
  51. * @param {Chunk} chunk chunk
  52. * @param {string} rootOutputDir root output directory
  53. * @returns {string} generated code
  54. */
  55. _generateBaseUri(chunk, rootOutputDir) {
  56. const options = chunk.getEntryOptions();
  57. const compilation = /** @type {Compilation} */ (this.compilation);
  58. const {
  59. outputOptions: { importMetaName }
  60. } = compilation;
  61. return renderBaseUri(
  62. options ? options.baseUri : undefined,
  63. `new URL(${JSON.stringify(rootOutputDir)}, ${importMetaName}.url)`
  64. );
  65. }
  66. /**
  67. * Generates runtime code for this runtime module.
  68. * @returns {string | null} runtime code
  69. */
  70. generate() {
  71. const compilation = /** @type {Compilation} */ (this.compilation);
  72. const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
  73. const chunk = /** @type {Chunk} */ (this.chunk);
  74. const environment = compilation.outputOptions.environment;
  75. const {
  76. runtimeTemplate,
  77. outputOptions: {
  78. importFunctionName,
  79. crossOriginLoading,
  80. charset,
  81. resourceHints
  82. }
  83. } = compilation;
  84. const dedupePrefetch = Boolean(resourceHints && resourceHints.dedupe);
  85. const fn = RuntimeGlobals.ensureChunkHandlers;
  86. const withBaseURI = this._runtimeRequirements.has(RuntimeGlobals.baseURI);
  87. const withExternalInstallChunk = this._runtimeRequirements.has(
  88. RuntimeGlobals.externalInstallChunk
  89. );
  90. const withAnalyzableImport = this._runtimeRequirements.has(
  91. RuntimeGlobals.analyzableChunkImport
  92. );
  93. const withLoading = this._runtimeRequirements.has(
  94. RuntimeGlobals.ensureChunkHandlers
  95. );
  96. const withOnChunkLoad = this._runtimeRequirements.has(
  97. RuntimeGlobals.onChunksLoaded
  98. );
  99. const withHmr = this._runtimeRequirements.has(
  100. RuntimeGlobals.hmrDownloadUpdateHandlers
  101. );
  102. const withHmrManifest = this._runtimeRequirements.has(
  103. RuntimeGlobals.hmrDownloadManifest
  104. );
  105. // `.f.j` serves `ensureChunk`: an analyzable import dispatches every handler but
  106. // this one. HMR's force-load knows only a chunk id, so it needs the loader too.
  107. const withJsLoading =
  108. withLoading &&
  109. (this._runtimeRequirements.has(RuntimeGlobals.ensureChunk) || withHmr);
  110. const { linkPreload, linkPrefetch } =
  111. ModuleChunkLoadingRuntimeModule.getCompilationHooks(compilation);
  112. const isNeutralPlatform = runtimeTemplate.isNeutralPlatform();
  113. const withPrefetch =
  114. (environment.document || isNeutralPlatform) &&
  115. this._runtimeRequirements.has(RuntimeGlobals.prefetchChunkHandlers) &&
  116. chunk.hasChildByOrder(chunkGraph, "prefetch", true, chunkHasJs);
  117. const withPreload =
  118. (environment.document || isNeutralPlatform) &&
  119. this._runtimeRequirements.has(RuntimeGlobals.preloadChunkHandlers) &&
  120. chunk.hasChildByOrder(chunkGraph, "preload", true, chunkHasJs);
  121. // Under module output each hinted chunk is a known file, so the urls are written
  122. // out and read by id rather than built from the chunk id at runtime.
  123. const chunkUrls =
  124. withPrefetch || withPreload
  125. ? runtimeTemplate.analyzableChunkScriptUrls(
  126. chunk,
  127. chunkGraph,
  128. this._runtimeRequirements,
  129. this
  130. )
  131. : null;
  132. const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
  133. const hasJsMatcher = compileBooleanMatcher(conditionMap);
  134. const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
  135. const rootOutputDir = runtimeTemplate.chunkRootOutputDir(chunk, true);
  136. const { publicPath } = compilation.outputOptions;
  137. // `import()` resolves a bare specifier as a package name, so a public path that
  138. // leaves one — empty, or a plain relative directory — needs an explicit `./`.
  139. // A runtime override can swap in an absolute path, so leave those alone.
  140. const chunkImportBase =
  141. publicPath === "auto"
  142. ? JSON.stringify(rootOutputDir)
  143. : typeof publicPath === "string" &&
  144. !/^(?:\.{0,2}\/|[a-zA-Z][\w+.-]*:)/.test(publicPath) &&
  145. !getAPIPlugin().usesRuntimePublicPathOverride(compilation)
  146. ? `"./" + ${RuntimeGlobals.publicPath}`
  147. : RuntimeGlobals.publicPath;
  148. const stateExpression = withHmr
  149. ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_module`
  150. : undefined;
  151. const cst = runtimeTemplate.renderConst();
  152. const lt = runtimeTemplate.renderLet();
  153. const installedChunksObject = `{\n${Template.indent(
  154. Array.from(initialChunkIds, (id) => `${JSON.stringify(id)}: 0`).join(
  155. ",\n"
  156. )
  157. )}\n}`;
  158. // Every part below that reads the table. A chunk asking only for `.b` gets this
  159. // module for the base uri alone, and then has nothing to look up.
  160. const withInstalledChunks =
  161. withLoading ||
  162. withExternalInstallChunk ||
  163. withAnalyzableImport ||
  164. withOnChunkLoad ||
  165. withHmr ||
  166. withPrefetch ||
  167. withPreload;
  168. // The url is read through a thunk so a runtime hinting at many chunks builds only
  169. // the one it appends.
  170. /**
  171. * @param {string} id expression naming the chunk whose url is wanted
  172. * @returns {string} expression evaluating to its url
  173. */
  174. const chunkUrl = (id) =>
  175. chunkUrls === null
  176. ? `${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(${id})`
  177. : `chunkUrls[${id}]()`;
  178. return Template.asString([
  179. withBaseURI
  180. ? this._generateBaseUri(chunk, rootOutputDir)
  181. : "// no baseURI",
  182. "",
  183. ...(chunkUrls
  184. ? [
  185. `${cst} chunkUrls = {\n${Template.indent(
  186. Array.from(
  187. chunkUrls,
  188. ([id, url]) =>
  189. `${JSON.stringify(String(id))}: ${runtimeTemplate.returningFunction(url)}`
  190. ).join(",\n")
  191. )}\n};`,
  192. ""
  193. ]
  194. : []),
  195. withInstalledChunks
  196. ? Template.asString([
  197. "// object to store loaded and loading chunks",
  198. "// undefined = chunk not loaded, null = chunk preloaded/prefetched",
  199. "// [resolve, Promise] = chunk loading, 0 = chunk loaded",
  200. `${cst} installedChunks = ${
  201. stateExpression
  202. ? runtimeTemplate.assignOr(
  203. stateExpression,
  204. installedChunksObject
  205. )
  206. : installedChunksObject
  207. };`
  208. ])
  209. : "// no installed chunks",
  210. "",
  211. withLoading || withExternalInstallChunk || withAnalyzableImport
  212. ? `${cst} installChunk = ${runtimeTemplate.basicFunction("data", [
  213. runtimeTemplate.destructureObject(
  214. [
  215. RuntimeGlobals.esmIds,
  216. RuntimeGlobals.esmModules,
  217. RuntimeGlobals.esmRuntime
  218. ],
  219. "data"
  220. ),
  221. '// add "modules" to the modules object,',
  222. '// then flag all "ids" as loaded and fire callback',
  223. "var moduleId, chunkId, i = 0;",
  224. `for(moduleId in ${RuntimeGlobals.esmModules}) {`,
  225. Template.indent([
  226. `if(${RuntimeGlobals.hasOwnProperty}(${RuntimeGlobals.esmModules}, moduleId)) {`,
  227. Template.indent(
  228. `${RuntimeGlobals.moduleFactories}[moduleId] = ${RuntimeGlobals.esmModules}[moduleId];`
  229. ),
  230. "}"
  231. ]),
  232. "}",
  233. `if(${RuntimeGlobals.esmRuntime}) ${RuntimeGlobals.esmRuntime}(${RuntimeGlobals.require});`,
  234. `for(;i < ${RuntimeGlobals.esmIds}.length; i++) {`,
  235. Template.indent([
  236. `chunkId = ${RuntimeGlobals.esmIds}[i];`,
  237. `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
  238. Template.indent("installedChunks[chunkId][0]();"),
  239. "}",
  240. "installedChunks[chunkId] = 0;"
  241. ]),
  242. "}",
  243. withOnChunkLoad ? `${RuntimeGlobals.onChunksLoaded}();` : ""
  244. ])}`
  245. : "// no install chunk",
  246. "",
  247. withJsLoading
  248. ? Template.asString([
  249. `${fn}.j = ${runtimeTemplate.basicFunction(
  250. "chunkId, promises",
  251. hasJsMatcher !== false
  252. ? Template.indent([
  253. "// import() chunk loading for javascript",
  254. `${lt} installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
  255. 'if(installedChunkData !== 0) { // 0 means "already installed".',
  256. Template.indent([
  257. "",
  258. '// a Promise means "currently loading".',
  259. "if(installedChunkData) {",
  260. Template.indent([
  261. "promises.push(installedChunkData[1]);"
  262. ]),
  263. "} else {",
  264. Template.indent([
  265. hasJsMatcher === true
  266. ? "if(true) { // all chunks have JS"
  267. : `if(${hasJsMatcher("chunkId")}) {`,
  268. Template.indent([
  269. "// setup Promise in chunk cache",
  270. `${lt} promise = ${importFunctionName}(${chunkImportBase} + ${
  271. RuntimeGlobals.getChunkScriptFilename
  272. }(chunkId)).then(installChunk, ${runtimeTemplate.basicFunction(
  273. "e",
  274. [
  275. "if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;",
  276. "throw e;"
  277. ]
  278. )});`,
  279. `promise = Promise.race([promise, new Promise(${runtimeTemplate.expressionFunction(
  280. "installedChunkData = installedChunks[chunkId] = [resolve]",
  281. "resolve"
  282. )})])`,
  283. "promises.push(installedChunkData[1] = promise);"
  284. ]),
  285. hasJsMatcher === true
  286. ? "}"
  287. : "} else installedChunks[chunkId] = 0;"
  288. ]),
  289. "}"
  290. ]),
  291. "}"
  292. ])
  293. : Template.indent(["installedChunks[chunkId] = 0;"])
  294. )};`
  295. ])
  296. : "// no chunk on demand loading",
  297. "",
  298. withPrefetch && hasJsMatcher !== false
  299. ? `${
  300. RuntimeGlobals.prefetchChunkHandlers
  301. }.j = ${runtimeTemplate.basicFunction("chunkId", [
  302. // prefetch is a browser-only resource hint; no-op without a DOM (e.g. node side of a universal build)
  303. isNeutralPlatform
  304. ? "if (typeof document === 'undefined') return;"
  305. : "",
  306. `if((!${
  307. RuntimeGlobals.hasOwnProperty
  308. }(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && ${
  309. hasJsMatcher === true ? "true" : hasJsMatcher("chunkId")
  310. }) {`,
  311. Template.indent([
  312. // A hint is best-effort, so an id no url was written for is
  313. // skipped rather than turned into a bogus href.
  314. ...(chunkUrls ? ["if(!chunkUrls[chunkId]) return;"] : []),
  315. "installedChunks[chunkId] = null;",
  316. linkPrefetch.call(
  317. Template.asString([
  318. `${cst} link = document.createElement('link');`,
  319. charset ? "link.charset = 'utf-8';" : "",
  320. crossOriginLoading
  321. ? `link.crossOrigin = ${JSON.stringify(
  322. crossOriginLoading
  323. )};`
  324. : "",
  325. `if (${RuntimeGlobals.scriptNonce}) {`,
  326. Template.indent(
  327. `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
  328. ),
  329. "}",
  330. 'link.rel = "prefetch";',
  331. 'link.as = "script";',
  332. `link.href = ${chunkUrl("chunkId")};`
  333. ]),
  334. chunk
  335. ),
  336. dedupePrefetch
  337. ? Template.asString([
  338. // Chrome re-requests a resource when a prefetch link is added
  339. // after it was already (pre)loaded via markup; skip in that case.
  340. `${cst} links = document.getElementsByTagName("link");`,
  341. `for(${lt} i = 0; i < links.length; i++) {`,
  342. Template.indent([
  343. `${cst} l = links[i];`,
  344. 'if(l.href === link.href && (l.rel === "prefetch" || l.rel === "preload" || l.rel === "modulepreload")) return;'
  345. ]),
  346. "}"
  347. ])
  348. : "",
  349. "document.head.appendChild(link);"
  350. ]),
  351. "}"
  352. ])};`
  353. : "// no prefetching",
  354. "",
  355. withPreload && hasJsMatcher !== false
  356. ? `${
  357. RuntimeGlobals.preloadChunkHandlers
  358. }.j = ${runtimeTemplate.basicFunction("chunkId", [
  359. // preload is a browser-only resource hint; no-op without a DOM (e.g. node side of a universal build)
  360. isNeutralPlatform
  361. ? "if (typeof document === 'undefined') return;"
  362. : "",
  363. `if((!${
  364. RuntimeGlobals.hasOwnProperty
  365. }(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && ${
  366. hasJsMatcher === true ? "true" : hasJsMatcher("chunkId")
  367. }) {`,
  368. Template.indent([
  369. // A hint is best-effort, so an id no url was written for is
  370. // skipped rather than turned into a bogus href.
  371. ...(chunkUrls ? ["if(!chunkUrls[chunkId]) return;"] : []),
  372. "installedChunks[chunkId] = null;",
  373. linkPreload.call(
  374. Template.asString([
  375. `${cst} link = document.createElement('link');`,
  376. charset ? "link.charset = 'utf-8';" : "",
  377. `if (${RuntimeGlobals.scriptNonce}) {`,
  378. Template.indent(
  379. `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
  380. ),
  381. "}",
  382. 'link.rel = "modulepreload";',
  383. `link.href = ${chunkUrl("chunkId")};`,
  384. crossOriginLoading
  385. ? crossOriginLoading === "use-credentials"
  386. ? 'link.crossOrigin = "use-credentials";'
  387. : Template.asString([
  388. "if (link.href.indexOf(window.location.origin + '/') !== 0) {",
  389. Template.indent(
  390. `link.crossOrigin = ${JSON.stringify(
  391. crossOriginLoading
  392. )};`
  393. ),
  394. "}"
  395. ])
  396. : ""
  397. ]),
  398. chunk
  399. ),
  400. "document.head.appendChild(link);"
  401. ]),
  402. "}"
  403. ])};`
  404. : "// no preloaded",
  405. "",
  406. withExternalInstallChunk
  407. ? Template.asString([
  408. `${RuntimeGlobals.externalInstallChunk} = installChunk;`
  409. ])
  410. : "// no external install chunk",
  411. "",
  412. withAnalyzableImport
  413. ? `${
  414. RuntimeGlobals.analyzableChunkImport
  415. } = ${runtimeTemplate.basicFunction("chunkId, importFn", [
  416. // `ensureChunk` with its `.j` half replaced by a literal `import()` a foreign
  417. // bundler can follow. The remaining handlers still run, so a chunk's css and
  418. // its prefetch/preload children are not lost by taking this path.
  419. `${lt} promises = [];`,
  420. `${lt} installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
  421. 'if(installedChunkData !== 0) { // 0 means "already installed".',
  422. Template.indent([
  423. '// a Promise means "currently loading".',
  424. "if(installedChunkData) {",
  425. Template.indent(["promises.push(installedChunkData[1]);"]),
  426. "} else {",
  427. Template.indent([
  428. `${lt} promise = importFn().then(installChunk, ${runtimeTemplate.basicFunction(
  429. "e",
  430. [
  431. "if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;",
  432. "throw e;"
  433. ]
  434. )});`,
  435. `promise = Promise.race([promise, new Promise(${runtimeTemplate.expressionFunction(
  436. "installedChunkData = installedChunks[chunkId] = [resolve]",
  437. "resolve"
  438. )})]);`,
  439. "promises.push((installedChunkData[1] = promise));"
  440. ]),
  441. "}"
  442. ]),
  443. "}",
  444. withLoading
  445. ? `Object.keys(${fn}).forEach(${runtimeTemplate.basicFunction(
  446. "key",
  447. [`if(key !== "j") ${fn}[key](chunkId, promises);`]
  448. )});`
  449. : "// no other chunk loading handlers",
  450. "return Promise.all(promises);"
  451. ])};`
  452. : "// no analyzable chunk import",
  453. "",
  454. withOnChunkLoad
  455. ? `${
  456. RuntimeGlobals.onChunksLoaded
  457. }.j = ${runtimeTemplate.returningFunction(
  458. "installedChunks[chunkId] === 0",
  459. "chunkId"
  460. )};`
  461. : "// no on chunks loaded",
  462. withHmr
  463. ? Template.asString([
  464. generateJavascriptHMR("module"),
  465. "",
  466. "function loadUpdateChunk(chunkId, updatedModulesList) {",
  467. Template.indent([
  468. `return new Promise(${runtimeTemplate.basicFunction(
  469. "resolve, reject",
  470. [
  471. "// start update chunk loading",
  472. `${cst} url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkUpdateScriptFilename}(chunkId);`,
  473. `${cst} onResolve = ${runtimeTemplate.basicFunction("obj", [
  474. `${cst} updatedModules = obj.${RuntimeGlobals.esmModules};`,
  475. `${cst} updatedRuntime = obj.${RuntimeGlobals.esmRuntime};`,
  476. "if(updatedRuntime) currentUpdateRuntime.push(updatedRuntime);",
  477. "for(var moduleId in updatedModules) {",
  478. Template.indent([
  479. `if(${RuntimeGlobals.hasOwnProperty}(updatedModules, moduleId)) {`,
  480. Template.indent([
  481. "currentUpdate[moduleId] = updatedModules[moduleId];",
  482. `${runtimeTemplate.optionalChaining("updatedModulesList", "push(moduleId)")};`
  483. ]),
  484. "}"
  485. ]),
  486. "}",
  487. "resolve(obj);"
  488. ])};`,
  489. `${cst} onReject = ${runtimeTemplate.basicFunction("error", [
  490. `${cst} errorMsg = error.message || 'unknown reason';`,
  491. "error.message = 'Loading hot update chunk ' + chunkId + ' failed.\\n(' + errorMsg + ')';",
  492. "error.name = 'ChunkLoadError';",
  493. "reject(error);"
  494. ])}`,
  495. `${cst} loadScript = ${runtimeTemplate.basicFunction(
  496. "url, onResolve, onReject",
  497. [
  498. `return ${importFunctionName}(/* webpackIgnore: true */ url).then(onResolve).catch(onReject)`
  499. ]
  500. )}`,
  501. "loadScript(url, onResolve, onReject);"
  502. ]
  503. )});`
  504. ]),
  505. "}",
  506. ""
  507. ])
  508. : "// no HMR",
  509. "",
  510. withHmrManifest
  511. ? Template.asString([
  512. `${
  513. RuntimeGlobals.hmrDownloadManifest
  514. } = ${runtimeTemplate.basicFunction("", [
  515. `return ${importFunctionName}(/* webpackIgnore: true */ ${RuntimeGlobals.publicPath} + ${
  516. RuntimeGlobals.getUpdateManifestFilename
  517. }()).then(${runtimeTemplate.basicFunction("obj", [
  518. "return obj.default;"
  519. ])}, ${runtimeTemplate.basicFunction("error", [
  520. "if(['MODULE_NOT_FOUND', 'ENOENT'].includes(error.code)) return;",
  521. "throw error;"
  522. ])});`
  523. ])};`
  524. ])
  525. : "// no HMR manifest"
  526. ]);
  527. }
  528. }
  529. ModuleChunkLoadingRuntimeModule.getCompilationHooks = createHooksRegistry(
  530. createCompilationHooks
  531. );
  532. module.exports = ModuleChunkLoadingRuntimeModule;