source: frontend/node_modules/webpack/lib/web/JsonpChunkLoadingRuntimeModule.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 16.1 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3*/
4
5"use strict";
6
7const { SyncWaterfallHook } = require("tapable");
8const Compilation = require("../Compilation");
9const RuntimeGlobals = require("../RuntimeGlobals");
10const RuntimeModule = require("../RuntimeModule");
11const Template = require("../Template");
12const {
13 generateJavascriptHMR
14} = require("../hmr/JavascriptHotModuleReplacementHelper");
15const chunkHasJs = require("../javascript/JavascriptModulesPlugin").chunkHasJs;
16const { getInitialChunkIds } = require("../javascript/StartupHelpers");
17const compileBooleanMatcher = require("../util/compileBooleanMatcher");
18
19/** @typedef {import("../Chunk")} Chunk */
20/** @typedef {import("../ChunkGraph")} ChunkGraph */
21/** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
22
23/**
24 * @typedef {object} JsonpCompilationPluginHooks
25 * @property {SyncWaterfallHook<[string, Chunk]>} linkPreload
26 * @property {SyncWaterfallHook<[string, Chunk]>} linkPrefetch
27 */
28
29/** @type {WeakMap<Compilation, JsonpCompilationPluginHooks>} */
30const compilationHooksMap = new WeakMap();
31
32class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
33 /**
34 * @param {Compilation} compilation the compilation
35 * @returns {JsonpCompilationPluginHooks} hooks
36 */
37 static getCompilationHooks(compilation) {
38 if (!(compilation instanceof Compilation)) {
39 throw new TypeError(
40 "The 'compilation' argument must be an instance of Compilation"
41 );
42 }
43 let hooks = compilationHooksMap.get(compilation);
44 if (hooks === undefined) {
45 hooks = {
46 linkPreload: new SyncWaterfallHook(["source", "chunk"]),
47 linkPrefetch: new SyncWaterfallHook(["source", "chunk"])
48 };
49 compilationHooksMap.set(compilation, hooks);
50 }
51 return hooks;
52 }
53
54 /**
55 * @param {ReadOnlyRuntimeRequirements} runtimeRequirements runtime requirements
56 */
57 constructor(runtimeRequirements) {
58 super("jsonp chunk loading", RuntimeModule.STAGE_ATTACH);
59 /** @type {ReadOnlyRuntimeRequirements} */
60 this._runtimeRequirements = runtimeRequirements;
61 }
62
63 /**
64 * @private
65 * @param {Chunk} chunk chunk
66 * @returns {string} generated code
67 */
68 _generateBaseUri(chunk) {
69 const options = chunk.getEntryOptions();
70 if (options && options.baseUri) {
71 return `${RuntimeGlobals.baseURI} = ${JSON.stringify(options.baseUri)};`;
72 }
73 return `${RuntimeGlobals.baseURI} = (typeof document !== 'undefined' && document.baseURI) || self.location.href;`;
74 }
75
76 /**
77 * Generates runtime code for this runtime module.
78 * @returns {string | null} runtime code
79 */
80 generate() {
81 const compilation = /** @type {Compilation} */ (this.compilation);
82 const {
83 runtimeTemplate,
84 outputOptions: {
85 chunkLoadingGlobal,
86 hotUpdateGlobal,
87 crossOriginLoading,
88 scriptType,
89 charset
90 }
91 } = compilation;
92 const globalObject = runtimeTemplate.globalObject;
93 const { linkPreload, linkPrefetch } =
94 JsonpChunkLoadingRuntimeModule.getCompilationHooks(compilation);
95 const fn = RuntimeGlobals.ensureChunkHandlers;
96 const withBaseURI = this._runtimeRequirements.has(RuntimeGlobals.baseURI);
97 const withLoading = this._runtimeRequirements.has(
98 RuntimeGlobals.ensureChunkHandlers
99 );
100 const withCallback = this._runtimeRequirements.has(
101 RuntimeGlobals.chunkCallback
102 );
103 const withOnChunkLoad = this._runtimeRequirements.has(
104 RuntimeGlobals.onChunksLoaded
105 );
106 const withHmr = this._runtimeRequirements.has(
107 RuntimeGlobals.hmrDownloadUpdateHandlers
108 );
109 const withHmrManifest = this._runtimeRequirements.has(
110 RuntimeGlobals.hmrDownloadManifest
111 );
112 const withFetchPriority = this._runtimeRequirements.has(
113 RuntimeGlobals.hasFetchPriority
114 );
115 const chunkLoadingGlobalExpr = `${globalObject}[${JSON.stringify(
116 chunkLoadingGlobal
117 )}]`;
118 const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
119 const chunk = /** @type {Chunk} */ (this.chunk);
120 const withPrefetch =
121 this._runtimeRequirements.has(RuntimeGlobals.prefetchChunkHandlers) &&
122 chunk.hasChildByOrder(chunkGraph, "prefetch", true, chunkHasJs);
123 const withPreload =
124 this._runtimeRequirements.has(RuntimeGlobals.preloadChunkHandlers) &&
125 chunk.hasChildByOrder(chunkGraph, "preload", true, chunkHasJs);
126 const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
127 const hasJsMatcher = compileBooleanMatcher(conditionMap);
128 const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
129
130 const stateExpression = withHmr
131 ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_jsonp`
132 : undefined;
133
134 return Template.asString([
135 withBaseURI ? this._generateBaseUri(chunk) : "// no baseURI",
136 "",
137 "// object to store loaded and loading chunks",
138 "// undefined = chunk not loaded, null = chunk preloaded/prefetched",
139 "// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded",
140 `var installedChunks = ${
141 stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
142 }{`,
143 Template.indent(
144 Array.from(initialChunkIds, (id) => `${JSON.stringify(id)}: 0`).join(
145 ",\n"
146 )
147 ),
148 "};",
149 "",
150 withLoading
151 ? Template.asString([
152 `${fn}.j = ${runtimeTemplate.basicFunction(
153 `chunkId, promises${withFetchPriority ? ", fetchPriority" : ""}`,
154 hasJsMatcher !== false
155 ? Template.indent([
156 "// JSONP chunk loading for javascript",
157 `var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
158 'if(installedChunkData !== 0) { // 0 means "already installed".',
159 Template.indent([
160 "",
161 '// a Promise means "currently loading".',
162 "if(installedChunkData) {",
163 Template.indent([
164 "promises.push(installedChunkData[2]);"
165 ]),
166 "} else {",
167 Template.indent([
168 hasJsMatcher === true
169 ? "if(true) { // all chunks have JS"
170 : `if(${hasJsMatcher("chunkId")}) {`,
171 Template.indent([
172 "// setup Promise in chunk cache",
173 `var promise = new Promise(${runtimeTemplate.expressionFunction(
174 "installedChunkData = installedChunks[chunkId] = [resolve, reject]",
175 "resolve, reject"
176 )});`,
177 "promises.push(installedChunkData[2] = promise);",
178 "",
179 "// start chunk loading",
180 `var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId);`,
181 "// create error before stack unwound to get useful stacktrace later",
182 "var error = new Error();",
183 `var loadingEnded = ${runtimeTemplate.basicFunction(
184 "event",
185 [
186 `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
187 Template.indent([
188 "installedChunkData = installedChunks[chunkId];",
189 "if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
190 "if(installedChunkData) {",
191 Template.indent([
192 "var errorType = event && (event.type === 'load' ? 'missing' : event.type);",
193 "var realSrc = event && event.target && event.target.src;",
194 "error.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
195 "error.name = 'ChunkLoadError';",
196 "error.type = errorType;",
197 "error.request = realSrc;",
198 "installedChunkData[1](error);"
199 ]),
200 "}"
201 ]),
202 "}"
203 ]
204 )};`,
205 `${
206 RuntimeGlobals.loadScript
207 }(url, loadingEnded, "chunk-" + chunkId, chunkId${
208 withFetchPriority ? ", fetchPriority" : ""
209 });`
210 ]),
211 hasJsMatcher === true
212 ? "}"
213 : "} else installedChunks[chunkId] = 0;"
214 ]),
215 "}"
216 ]),
217 "}"
218 ])
219 : Template.indent(["installedChunks[chunkId] = 0;"])
220 )};`
221 ])
222 : "// no chunk on demand loading",
223 "",
224 withPrefetch && hasJsMatcher !== false
225 ? `${
226 RuntimeGlobals.prefetchChunkHandlers
227 }.j = ${runtimeTemplate.basicFunction("chunkId", [
228 `if((!${
229 RuntimeGlobals.hasOwnProperty
230 }(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && ${
231 hasJsMatcher === true ? "true" : hasJsMatcher("chunkId")
232 }) {`,
233 Template.indent([
234 "installedChunks[chunkId] = null;",
235 linkPrefetch.call(
236 Template.asString([
237 "var link = document.createElement('link');",
238 charset ? "link.charset = 'utf-8';" : "",
239 crossOriginLoading
240 ? `link.crossOrigin = ${JSON.stringify(
241 crossOriginLoading
242 )};`
243 : "",
244 `if (${RuntimeGlobals.scriptNonce}) {`,
245 Template.indent(
246 `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
247 ),
248 "}",
249 'link.rel = "prefetch";',
250 'link.as = "script";',
251 `link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId);`
252 ]),
253 chunk
254 ),
255 "document.head.appendChild(link);"
256 ]),
257 "}"
258 ])};`
259 : "// no prefetching",
260 "",
261 withPreload && hasJsMatcher !== false
262 ? `${
263 RuntimeGlobals.preloadChunkHandlers
264 }.j = ${runtimeTemplate.basicFunction("chunkId", [
265 `if((!${
266 RuntimeGlobals.hasOwnProperty
267 }(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && ${
268 hasJsMatcher === true ? "true" : hasJsMatcher("chunkId")
269 }) {`,
270 Template.indent([
271 "installedChunks[chunkId] = null;",
272 linkPreload.call(
273 Template.asString([
274 "var link = document.createElement('link');",
275 scriptType && scriptType !== "module"
276 ? `link.type = ${JSON.stringify(scriptType)};`
277 : "",
278 charset ? "link.charset = 'utf-8';" : "",
279 `if (${RuntimeGlobals.scriptNonce}) {`,
280 Template.indent(
281 `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
282 ),
283 "}",
284 scriptType === "module"
285 ? 'link.rel = "modulepreload";'
286 : 'link.rel = "preload";',
287 scriptType === "module" ? "" : 'link.as = "script";',
288 `link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId);`,
289 crossOriginLoading
290 ? crossOriginLoading === "use-credentials"
291 ? 'link.crossOrigin = "use-credentials";'
292 : Template.asString([
293 "if (link.href.indexOf(window.location.origin + '/') !== 0) {",
294 Template.indent(
295 `link.crossOrigin = ${JSON.stringify(
296 crossOriginLoading
297 )};`
298 ),
299 "}"
300 ])
301 : ""
302 ]),
303 chunk
304 ),
305 "document.head.appendChild(link);"
306 ]),
307 "}"
308 ])};`
309 : "// no preloaded",
310 "",
311 withHmr
312 ? Template.asString([
313 "var currentUpdatedModulesList;",
314 "var waitingUpdateResolves = {};",
315 "function loadUpdateChunk(chunkId, updatedModulesList) {",
316 Template.indent([
317 "currentUpdatedModulesList = updatedModulesList;",
318 `return new Promise(${runtimeTemplate.basicFunction(
319 "resolve, reject",
320 [
321 "waitingUpdateResolves[chunkId] = resolve;",
322 "// start update chunk loading",
323 `var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkUpdateScriptFilename}(chunkId);`,
324 "// create error before stack unwound to get useful stacktrace later",
325 "var error = new Error();",
326 `var loadingEnded = ${runtimeTemplate.basicFunction("event", [
327 "if(waitingUpdateResolves[chunkId]) {",
328 Template.indent([
329 "waitingUpdateResolves[chunkId] = undefined",
330 "var errorType = event && (event.type === 'load' ? 'missing' : event.type);",
331 "var realSrc = event && event.target && event.target.src;",
332 "error.message = 'Loading hot update chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
333 "error.name = 'ChunkLoadError';",
334 "error.type = errorType;",
335 "error.request = realSrc;",
336 "reject(error);"
337 ]),
338 "}"
339 ])};`,
340 `${RuntimeGlobals.loadScript}(url, loadingEnded);`
341 ]
342 )});`
343 ]),
344 "}",
345 "",
346 `${globalObject}[${JSON.stringify(
347 hotUpdateGlobal
348 )}] = ${runtimeTemplate.basicFunction(
349 "chunkId, moreModules, runtime",
350 [
351 "for(var moduleId in moreModules) {",
352 Template.indent([
353 `if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
354 Template.indent([
355 "currentUpdate[moduleId] = moreModules[moduleId];",
356 "if(currentUpdatedModulesList) currentUpdatedModulesList.push(moduleId);"
357 ]),
358 "}"
359 ]),
360 "}",
361 "if(runtime) currentUpdateRuntime.push(runtime);",
362 "if(waitingUpdateResolves[chunkId]) {",
363 Template.indent([
364 "waitingUpdateResolves[chunkId]();",
365 "waitingUpdateResolves[chunkId] = undefined;"
366 ]),
367 "}"
368 ]
369 )};`,
370 "",
371 generateJavascriptHMR("jsonp")
372 ])
373 : "// no HMR",
374 "",
375 withHmrManifest
376 ? Template.asString([
377 `${
378 RuntimeGlobals.hmrDownloadManifest
379 } = ${runtimeTemplate.basicFunction("", [
380 'if (typeof fetch === "undefined") throw new Error("No browser support: need fetch API");',
381 `return fetch(${RuntimeGlobals.publicPath} + ${
382 RuntimeGlobals.getUpdateManifestFilename
383 }()).then(${runtimeTemplate.basicFunction("response", [
384 "if(response.status === 404) return; // no update available",
385 'if(!response.ok) throw new Error("Failed to fetch update manifest " + response.statusText);',
386 "return response.json();"
387 ])});`
388 ])};`
389 ])
390 : "// no HMR manifest",
391 "",
392 withOnChunkLoad
393 ? `${
394 RuntimeGlobals.onChunksLoaded
395 }.j = ${runtimeTemplate.returningFunction(
396 "installedChunks[chunkId] === 0",
397 "chunkId"
398 )};`
399 : "// no on chunks loaded",
400 "",
401 withCallback || withLoading
402 ? Template.asString([
403 "// install a JSONP callback for chunk loading",
404 `var webpackJsonpCallback = ${runtimeTemplate.basicFunction(
405 "parentChunkLoadingFunction, data",
406 [
407 runtimeTemplate.destructureArray(
408 ["chunkIds", "moreModules", "runtime"],
409 "data"
410 ),
411 '// add "moreModules" to the modules object,',
412 '// then flag all "chunkIds" as loaded and fire callback',
413 "var moduleId, chunkId, i = 0;",
414 `if(chunkIds.some(${runtimeTemplate.returningFunction(
415 "installedChunks[id] !== 0",
416 "id"
417 )})) {`,
418 Template.indent([
419 "for(moduleId in moreModules) {",
420 Template.indent([
421 `if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
422 Template.indent(
423 `${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
424 ),
425 "}"
426 ]),
427 "}",
428 `if(runtime) var result = runtime(${RuntimeGlobals.require});`
429 ]),
430 "}",
431 "if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);",
432 "for(;i < chunkIds.length; i++) {",
433 Template.indent([
434 "chunkId = chunkIds[i];",
435 `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
436 Template.indent("installedChunks[chunkId][0]();"),
437 "}",
438 "installedChunks[chunkId] = 0;"
439 ]),
440 "}",
441 withOnChunkLoad
442 ? `return ${RuntimeGlobals.onChunksLoaded}(result);`
443 : ""
444 ]
445 )}`,
446 "",
447 `var chunkLoadingGlobal = ${chunkLoadingGlobalExpr} = ${chunkLoadingGlobalExpr} || [];`,
448 "chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));",
449 "chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));"
450 ])
451 : "// no jsonp function"
452 ]);
453 }
454}
455
456module.exports = JsonpChunkLoadingRuntimeModule;
Note: See TracBrowser for help on using the repository browser.