CssLoadingRuntimeModule.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { SyncWaterfallHook } = require("tapable");
  7. const Compilation = require("../Compilation");
  8. const RuntimeGlobals = require("../RuntimeGlobals");
  9. const RuntimeModule = require("../RuntimeModule");
  10. const Template = require("../Template");
  11. const compileBooleanMatcher = require("../util/compileBooleanMatcher");
  12. const { chunkHasCss } = require("./CssModulesPlugin");
  13. /** @typedef {import("../Chunk")} Chunk */
  14. /** @typedef {import("../ChunkGraph")} ChunkGraph */
  15. /** @typedef {import("../Compilation").RuntimeRequirementsContext} RuntimeRequirementsContext */
  16. /** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
  17. /**
  18. * @typedef {object} CssLoadingRuntimeModulePluginHooks
  19. * @property {SyncWaterfallHook<[string, Chunk]>} createStylesheet
  20. * @property {SyncWaterfallHook<[string, Chunk]>} linkPreload
  21. * @property {SyncWaterfallHook<[string, Chunk]>} linkPrefetch
  22. */
  23. /** @type {WeakMap<Compilation, CssLoadingRuntimeModulePluginHooks>} */
  24. const compilationHooksMap = new WeakMap();
  25. class CssLoadingRuntimeModule extends RuntimeModule {
  26. /**
  27. * @param {Compilation} compilation the compilation
  28. * @returns {CssLoadingRuntimeModulePluginHooks} hooks
  29. */
  30. static getCompilationHooks(compilation) {
  31. if (!(compilation instanceof Compilation)) {
  32. throw new TypeError(
  33. "The 'compilation' argument must be an instance of Compilation"
  34. );
  35. }
  36. let hooks = compilationHooksMap.get(compilation);
  37. if (hooks === undefined) {
  38. hooks = {
  39. createStylesheet: new SyncWaterfallHook(["source", "chunk"]),
  40. linkPreload: new SyncWaterfallHook(["source", "chunk"]),
  41. linkPrefetch: new SyncWaterfallHook(["source", "chunk"])
  42. };
  43. compilationHooksMap.set(compilation, hooks);
  44. }
  45. return hooks;
  46. }
  47. /**
  48. * @param {ReadOnlyRuntimeRequirements} runtimeRequirements runtime requirements
  49. */
  50. constructor(runtimeRequirements) {
  51. super("css loading", 10);
  52. this._runtimeRequirements = runtimeRequirements;
  53. }
  54. /**
  55. * @returns {string | null} runtime code
  56. */
  57. generate() {
  58. const { _runtimeRequirements } = this;
  59. const compilation = /** @type {Compilation} */ (this.compilation);
  60. const chunk = /** @type {Chunk} */ (this.chunk);
  61. const {
  62. chunkGraph,
  63. runtimeTemplate,
  64. outputOptions: {
  65. crossOriginLoading,
  66. uniqueName,
  67. chunkLoadTimeout: loadTimeout,
  68. cssHeadDataCompression: withCompression
  69. }
  70. } = compilation;
  71. const fn = RuntimeGlobals.ensureChunkHandlers;
  72. const conditionMap = chunkGraph.getChunkConditionMap(
  73. /** @type {Chunk} */ (chunk),
  74. /**
  75. * @param {Chunk} chunk the chunk
  76. * @param {ChunkGraph} chunkGraph the chunk graph
  77. * @returns {boolean} true, if the chunk has css
  78. */
  79. (chunk, chunkGraph) =>
  80. !!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css")
  81. );
  82. const hasCssMatcher = compileBooleanMatcher(conditionMap);
  83. const withLoading =
  84. _runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) &&
  85. hasCssMatcher !== false;
  86. const withPrefetch = this._runtimeRequirements.has(
  87. RuntimeGlobals.prefetchChunkHandlers
  88. );
  89. const withPreload = this._runtimeRequirements.has(
  90. RuntimeGlobals.preloadChunkHandlers
  91. );
  92. /** @type {boolean} */
  93. const withHmr = _runtimeRequirements.has(
  94. RuntimeGlobals.hmrDownloadUpdateHandlers
  95. );
  96. /** @type {Set<number | string | null>} */
  97. const initialChunkIdsWithCss = new Set();
  98. /** @type {Set<number | string | null>} */
  99. const initialChunkIdsWithoutCss = new Set();
  100. for (const c of /** @type {Chunk} */ (chunk).getAllInitialChunks()) {
  101. (chunkHasCss(c, chunkGraph)
  102. ? initialChunkIdsWithCss
  103. : initialChunkIdsWithoutCss
  104. ).add(c.id);
  105. }
  106. if (!withLoading && !withHmr && initialChunkIdsWithCss.size === 0) {
  107. return null;
  108. }
  109. const { linkPreload, linkPrefetch } =
  110. CssLoadingRuntimeModule.getCompilationHooks(compilation);
  111. const withFetchPriority = _runtimeRequirements.has(
  112. RuntimeGlobals.hasFetchPriority
  113. );
  114. const { createStylesheet } =
  115. CssLoadingRuntimeModule.getCompilationHooks(compilation);
  116. const stateExpression = withHmr
  117. ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_css`
  118. : undefined;
  119. const code = Template.asString([
  120. "link = document.createElement('link');",
  121. `if (${RuntimeGlobals.scriptNonce}) {`,
  122. Template.indent(
  123. `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
  124. ),
  125. "}",
  126. uniqueName
  127. ? 'link.setAttribute("data-webpack", uniqueName + ":" + key);'
  128. : "",
  129. withFetchPriority
  130. ? Template.asString([
  131. "if(fetchPriority) {",
  132. Template.indent(
  133. 'link.setAttribute("fetchpriority", fetchPriority);'
  134. ),
  135. "}"
  136. ])
  137. : "",
  138. "link.setAttribute(loadingAttribute, 1);",
  139. 'link.rel = "stylesheet";',
  140. "link.href = url;",
  141. crossOriginLoading
  142. ? crossOriginLoading === "use-credentials"
  143. ? 'link.crossOrigin = "use-credentials";'
  144. : Template.asString([
  145. "if (link.href.indexOf(window.location.origin + '/') !== 0) {",
  146. Template.indent(
  147. `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
  148. ),
  149. "}"
  150. ])
  151. : ""
  152. ]);
  153. /** @type {(str: string) => number} */
  154. const cc = str => str.charCodeAt(0);
  155. const name = uniqueName
  156. ? runtimeTemplate.concatenation(
  157. "--webpack-",
  158. { expr: "uniqueName" },
  159. "-",
  160. { expr: "chunkId" }
  161. )
  162. : runtimeTemplate.concatenation("--webpack-", { expr: "chunkId" });
  163. return Template.asString([
  164. "// object to store loaded and loading chunks",
  165. "// undefined = chunk not loaded, null = chunk preloaded/prefetched",
  166. "// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded",
  167. `var installedChunks = ${
  168. stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
  169. }{${Array.from(
  170. initialChunkIdsWithoutCss,
  171. id => `${JSON.stringify(id)}:0`
  172. ).join(",")}};`,
  173. "",
  174. uniqueName
  175. ? `var uniqueName = ${JSON.stringify(
  176. runtimeTemplate.outputOptions.uniqueName
  177. )};`
  178. : "// data-webpack is not used as build has no uniqueName",
  179. `var loadCssChunkData = ${runtimeTemplate.basicFunction(
  180. "target, link, chunkId",
  181. [
  182. `var data, token = "", token2 = "", exports = {}, ${
  183. withHmr ? "moduleIds = [], " : ""
  184. }name = ${name}, i, cc = 1;`,
  185. "try {",
  186. Template.indent([
  187. "if(!link) link = loadStylesheet(chunkId);",
  188. // `link.sheet.rules` for legacy browsers
  189. "var cssRules = link.sheet.cssRules || link.sheet.rules;",
  190. "var j = cssRules.length - 1;",
  191. "while(j > -1 && !data) {",
  192. Template.indent([
  193. "var style = cssRules[j--].style;",
  194. "if(!style) continue;",
  195. `data = style.getPropertyValue(name);`
  196. ]),
  197. "}"
  198. ]),
  199. "}catch(e){}",
  200. "if(!data) {",
  201. Template.indent([
  202. "data = getComputedStyle(document.head).getPropertyValue(name);"
  203. ]),
  204. "}",
  205. "if(!data) return [];",
  206. withCompression
  207. ? Template.asString([
  208. // LZW decode
  209. `var map = {}, char = data[0], oldPhrase = char, decoded = char, code = 256, maxCode = ${"\uffff".charCodeAt(
  210. 0
  211. )}, phrase;`,
  212. "for (i = 1; i < data.length; i++) {",
  213. Template.indent([
  214. "cc = data[i].charCodeAt(0);",
  215. "if (cc < 256) phrase = data[i]; else phrase = map[cc] ? map[cc] : (oldPhrase + char);",
  216. "decoded += phrase;",
  217. "char = phrase.charAt(0);",
  218. "map[code] = oldPhrase + char;",
  219. "if (++code > maxCode) { code = 256; map = {}; }",
  220. "oldPhrase = phrase;"
  221. ]),
  222. "}",
  223. "data = decoded;"
  224. ])
  225. : "// css head data compression is disabled",
  226. "for(i = 0; cc; i++) {",
  227. Template.indent([
  228. "cc = data.charCodeAt(i);",
  229. `if(cc == ${cc(":")}) { token2 = token; token = ""; }`,
  230. `else if(cc == ${cc(
  231. "/"
  232. )}) { token = token.replace(/^_/, ""); token2 = token2.replace(/^_/, ""); exports[token2] = token; token = ""; token2 = ""; }`,
  233. `else if(cc == ${cc("&")}) { ${
  234. RuntimeGlobals.makeNamespaceObject
  235. }(exports); }`,
  236. `else if(!cc || cc == ${cc(
  237. ","
  238. )}) { token = token.replace(/^_/, ""); target[token] = (${runtimeTemplate.basicFunction(
  239. "exports, module",
  240. `module.exports = exports;`
  241. )}).bind(null, exports); ${
  242. withHmr ? "moduleIds.push(token); " : ""
  243. }token = ""; token2 = ""; exports = {}; }`,
  244. `else if(cc == ${cc("\\")}) { token += data[++i] }`,
  245. `else { token += data[i]; }`
  246. ]),
  247. "}",
  248. `${
  249. withHmr ? `if(target == ${RuntimeGlobals.moduleFactories}) ` : ""
  250. }installedChunks[chunkId] = 0;`,
  251. withHmr ? "return moduleIds;" : ""
  252. ]
  253. )}`,
  254. 'var loadingAttribute = "data-webpack-loading";',
  255. `var loadStylesheet = ${runtimeTemplate.basicFunction(
  256. "chunkId, url, done" +
  257. (withHmr ? ", hmr" : "") +
  258. (withFetchPriority ? ", fetchPriority" : ""),
  259. [
  260. 'var link, needAttach, key = "chunk-" + chunkId;',
  261. withHmr ? "if(!hmr) {" : "",
  262. 'var links = document.getElementsByTagName("link");',
  263. "for(var i = 0; i < links.length; i++) {",
  264. Template.indent([
  265. "var l = links[i];",
  266. `if(l.rel == "stylesheet" && (${
  267. withHmr
  268. ? 'l.href.startsWith(url) || l.getAttribute("href").startsWith(url)'
  269. : 'l.href == url || l.getAttribute("href") == url'
  270. }${
  271. uniqueName
  272. ? ' || l.getAttribute("data-webpack") == uniqueName + ":" + key'
  273. : ""
  274. })) { link = l; break; }`
  275. ]),
  276. "}",
  277. "if(!done) return link;",
  278. withHmr ? "}" : "",
  279. "if(!link) {",
  280. Template.indent([
  281. "needAttach = true;",
  282. createStylesheet.call(code, /** @type {Chunk} */ (this.chunk))
  283. ]),
  284. "}",
  285. `var onLinkComplete = ${runtimeTemplate.basicFunction(
  286. "prev, event",
  287. Template.asString([
  288. "link.onerror = link.onload = null;",
  289. "link.removeAttribute(loadingAttribute);",
  290. "clearTimeout(timeout);",
  291. 'if(event && event.type != "load") link.parentNode.removeChild(link)',
  292. "done(event);",
  293. "if(prev) return prev(event);"
  294. ])
  295. )};`,
  296. "if(link.getAttribute(loadingAttribute)) {",
  297. Template.indent([
  298. `var timeout = setTimeout(onLinkComplete.bind(null, undefined, { type: 'timeout', target: link }), ${loadTimeout});`,
  299. "link.onerror = onLinkComplete.bind(null, link.onerror);",
  300. "link.onload = onLinkComplete.bind(null, link.onload);"
  301. ]),
  302. "} else onLinkComplete(undefined, { type: 'load', target: link });", // We assume any existing stylesheet is render blocking
  303. withHmr ? "hmr ? document.head.insertBefore(link, hmr) :" : "",
  304. "needAttach && document.head.appendChild(link);",
  305. "return link;"
  306. ]
  307. )};`,
  308. initialChunkIdsWithCss.size > 2
  309. ? `${JSON.stringify(
  310. Array.from(initialChunkIdsWithCss)
  311. )}.forEach(loadCssChunkData.bind(null, ${
  312. RuntimeGlobals.moduleFactories
  313. }, 0));`
  314. : initialChunkIdsWithCss.size > 0
  315. ? `${Array.from(
  316. initialChunkIdsWithCss,
  317. id =>
  318. `loadCssChunkData(${
  319. RuntimeGlobals.moduleFactories
  320. }, 0, ${JSON.stringify(id)});`
  321. ).join("")}`
  322. : "// no initial css",
  323. "",
  324. withLoading
  325. ? Template.asString([
  326. `${fn}.css = ${runtimeTemplate.basicFunction(
  327. `chunkId, promises${withFetchPriority ? " , fetchPriority" : ""}`,
  328. [
  329. "// css chunk loading",
  330. `var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
  331. 'if(installedChunkData !== 0) { // 0 means "already installed".',
  332. Template.indent([
  333. "",
  334. '// a Promise means "currently loading".',
  335. "if(installedChunkData) {",
  336. Template.indent(["promises.push(installedChunkData[2]);"]),
  337. "} else {",
  338. Template.indent([
  339. hasCssMatcher === true
  340. ? "if(true) { // all chunks have CSS"
  341. : `if(${hasCssMatcher("chunkId")}) {`,
  342. Template.indent([
  343. "// setup Promise in chunk cache",
  344. `var promise = new Promise(${runtimeTemplate.expressionFunction(
  345. `installedChunkData = installedChunks[chunkId] = [resolve, reject]`,
  346. "resolve, reject"
  347. )});`,
  348. "promises.push(installedChunkData[2] = promise);",
  349. "",
  350. "// start chunk loading",
  351. `var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
  352. "// create error before stack unwound to get useful stacktrace later",
  353. "var error = new Error();",
  354. `var loadingEnded = ${runtimeTemplate.basicFunction(
  355. "event",
  356. [
  357. `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
  358. Template.indent([
  359. "installedChunkData = installedChunks[chunkId];",
  360. "if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
  361. "if(installedChunkData) {",
  362. Template.indent([
  363. 'if(event.type !== "load") {',
  364. Template.indent([
  365. "var errorType = event && event.type;",
  366. "var realHref = event && event.target && event.target.href;",
  367. "error.message = 'Loading css chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realHref + ')';",
  368. "error.name = 'ChunkLoadError';",
  369. "error.type = errorType;",
  370. "error.request = realHref;",
  371. "installedChunkData[1](error);"
  372. ]),
  373. "} else {",
  374. Template.indent([
  375. `loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`,
  376. "installedChunkData[0]();"
  377. ]),
  378. "}"
  379. ]),
  380. "}"
  381. ]),
  382. "}"
  383. ]
  384. )};`,
  385. `var link = loadStylesheet(chunkId, url, loadingEnded${
  386. withFetchPriority ? ", fetchPriority" : ""
  387. });`
  388. ]),
  389. "} else installedChunks[chunkId] = 0;"
  390. ]),
  391. "}"
  392. ]),
  393. "}"
  394. ]
  395. )};`
  396. ])
  397. : "// no chunk loading",
  398. "",
  399. withPrefetch && hasCssMatcher !== false
  400. ? `${
  401. RuntimeGlobals.prefetchChunkHandlers
  402. }.s = ${runtimeTemplate.basicFunction("chunkId", [
  403. `if((!${
  404. RuntimeGlobals.hasOwnProperty
  405. }(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && ${
  406. hasCssMatcher === true ? "true" : hasCssMatcher("chunkId")
  407. }) {`,
  408. Template.indent([
  409. "installedChunks[chunkId] = null;",
  410. linkPrefetch.call(
  411. Template.asString([
  412. "var link = document.createElement('link');",
  413. crossOriginLoading
  414. ? `link.crossOrigin = ${JSON.stringify(
  415. crossOriginLoading
  416. )};`
  417. : "",
  418. `if (${RuntimeGlobals.scriptNonce}) {`,
  419. Template.indent(
  420. `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
  421. ),
  422. "}",
  423. 'link.rel = "prefetch";',
  424. 'link.as = "style";',
  425. `link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`
  426. ]),
  427. chunk
  428. ),
  429. "document.head.appendChild(link);"
  430. ]),
  431. "}"
  432. ])};`
  433. : "// no prefetching",
  434. "",
  435. withPreload && hasCssMatcher !== false
  436. ? `${
  437. RuntimeGlobals.preloadChunkHandlers
  438. }.s = ${runtimeTemplate.basicFunction("chunkId", [
  439. `if((!${
  440. RuntimeGlobals.hasOwnProperty
  441. }(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && ${
  442. hasCssMatcher === true ? "true" : hasCssMatcher("chunkId")
  443. }) {`,
  444. Template.indent([
  445. "installedChunks[chunkId] = null;",
  446. linkPreload.call(
  447. Template.asString([
  448. "var link = document.createElement('link');",
  449. "link.charset = 'utf-8';",
  450. `if (${RuntimeGlobals.scriptNonce}) {`,
  451. Template.indent(
  452. `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
  453. ),
  454. "}",
  455. 'link.rel = "preload";',
  456. 'link.as = "style";',
  457. `link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
  458. crossOriginLoading
  459. ? crossOriginLoading === "use-credentials"
  460. ? 'link.crossOrigin = "use-credentials";'
  461. : Template.asString([
  462. "if (link.href.indexOf(window.location.origin + '/') !== 0) {",
  463. Template.indent(
  464. `link.crossOrigin = ${JSON.stringify(
  465. crossOriginLoading
  466. )};`
  467. ),
  468. "}"
  469. ])
  470. : ""
  471. ]),
  472. chunk
  473. ),
  474. "document.head.appendChild(link);"
  475. ]),
  476. "}"
  477. ])};`
  478. : "// no preloaded",
  479. withHmr
  480. ? Template.asString([
  481. "var oldTags = [];",
  482. "var newTags = [];",
  483. `var applyHandler = ${runtimeTemplate.basicFunction("options", [
  484. `return { dispose: ${runtimeTemplate.basicFunction(
  485. "",
  486. []
  487. )}, apply: ${runtimeTemplate.basicFunction("", [
  488. "var moduleIds = [];",
  489. `newTags.forEach(${runtimeTemplate.expressionFunction(
  490. "info[1].sheet.disabled = false",
  491. "info"
  492. )});`,
  493. "while(oldTags.length) {",
  494. Template.indent([
  495. "var oldTag = oldTags.pop();",
  496. "if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);"
  497. ]),
  498. "}",
  499. "while(newTags.length) {",
  500. Template.indent([
  501. `var info = newTags.pop();`,
  502. `var chunkModuleIds = loadCssChunkData(${RuntimeGlobals.moduleFactories}, info[1], info[0]);`,
  503. `chunkModuleIds.forEach(${runtimeTemplate.expressionFunction(
  504. "moduleIds.push(id)",
  505. "id"
  506. )});`
  507. ]),
  508. "}",
  509. "return moduleIds;"
  510. ])} };`
  511. ])}`,
  512. `var cssTextKey = ${runtimeTemplate.returningFunction(
  513. `Array.from(link.sheet.cssRules, ${runtimeTemplate.returningFunction(
  514. "r.cssText",
  515. "r"
  516. )}).join()`,
  517. "link"
  518. )}`,
  519. `${
  520. RuntimeGlobals.hmrDownloadUpdateHandlers
  521. }.css = ${runtimeTemplate.basicFunction(
  522. "chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList",
  523. [
  524. "applyHandlers.push(applyHandler);",
  525. `chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [
  526. `var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
  527. `var url = ${RuntimeGlobals.publicPath} + filename;`,
  528. "var oldTag = loadStylesheet(chunkId, url);",
  529. "if(!oldTag) return;",
  530. `promises.push(new Promise(${runtimeTemplate.basicFunction(
  531. "resolve, reject",
  532. [
  533. `var link = loadStylesheet(chunkId, url + (url.indexOf("?") < 0 ? "?" : "&") + "hmr=" + Date.now(), ${runtimeTemplate.basicFunction(
  534. "event",
  535. [
  536. 'if(event.type !== "load") {',
  537. Template.indent([
  538. "var errorType = event && event.type;",
  539. "var realHref = event && event.target && event.target.href;",
  540. "error.message = 'Loading css hot update chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realHref + ')';",
  541. "error.name = 'ChunkLoadError';",
  542. "error.type = errorType;",
  543. "error.request = realHref;",
  544. "reject(error);"
  545. ]),
  546. "} else {",
  547. Template.indent([
  548. "try { if(cssTextKey(oldTag) == cssTextKey(link)) { if(link.parentNode) link.parentNode.removeChild(link); return resolve(); } } catch(e) {}",
  549. "var factories = {};",
  550. "loadCssChunkData(factories, link, chunkId);",
  551. `Object.keys(factories).forEach(${runtimeTemplate.expressionFunction(
  552. "updatedModulesList.push(id)",
  553. "id"
  554. )})`,
  555. "link.sheet.disabled = true;",
  556. "oldTags.push(oldTag);",
  557. "newTags.push([chunkId, link]);",
  558. "resolve();"
  559. ]),
  560. "}"
  561. ]
  562. )}, oldTag);`
  563. ]
  564. )}));`
  565. ])});`
  566. ]
  567. )}`
  568. ])
  569. : "// no hmr"
  570. ]);
  571. }
  572. }
  573. module.exports = CssLoadingRuntimeModule;