Skip to content

Commit dcdd094

Browse files
committed
refactor(runtime): move runtime logic for webpack 5 into runtime module
1 parent 9465a4c commit dcdd094

File tree

2 files changed

+289
-143
lines changed

2 files changed

+289
-143
lines changed

src/CssLoadingRuntimeModule.js

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { RuntimeGlobals, RuntimeModule, Template, util } from 'webpack';
2+
3+
import { MODULE_TYPE } from './utils';
4+
5+
const {
6+
comparators: { compareModulesByIdentifier },
7+
} = util;
8+
9+
const getCssChunkObject = (mainChunk, compilation) => {
10+
const obj = {};
11+
const { chunkGraph } = compilation;
12+
13+
for (const chunk of mainChunk.getAllAsyncChunks()) {
14+
const modules = chunkGraph.getOrderedChunkModulesIterable(
15+
chunk,
16+
compareModulesByIdentifier
17+
);
18+
for (const module of modules) {
19+
if (module.type === MODULE_TYPE) {
20+
obj[chunk.id] = 1;
21+
break;
22+
}
23+
}
24+
}
25+
26+
return obj;
27+
};
28+
29+
module.exports = class CssLoadingRuntimeModule extends RuntimeModule {
30+
constructor(runtimeRequirements) {
31+
super('css loading', 10);
32+
this.runtimeRequirements = runtimeRequirements;
33+
}
34+
35+
generate() {
36+
const { chunk, compilation, runtimeRequirements } = this;
37+
const {
38+
runtimeTemplate,
39+
outputOptions: { crossOriginLoading },
40+
} = compilation;
41+
const chunkMap = getCssChunkObject(chunk, compilation);
42+
43+
if (Object.keys(chunkMap).length === 0) return null;
44+
45+
const withLoading = runtimeRequirements.has(
46+
RuntimeGlobals.ensureChunkHandlers
47+
);
48+
49+
return Template.asString([
50+
'// object to store loaded CSS chunks',
51+
'var installedCssChunks = {',
52+
Template.indent(
53+
chunk.ids.map((id) => `${JSON.stringify(id)}: 0`).join(',\n')
54+
),
55+
'};',
56+
'',
57+
withLoading
58+
? Template.asString([
59+
`${
60+
RuntimeGlobals.ensureChunkHandlers
61+
}.miniCss = ${runtimeTemplate.basicFunction('chunkId, promises', [
62+
`var cssChunks = ${JSON.stringify(chunkMap)};`,
63+
'if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);',
64+
'else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {',
65+
Template.indent([
66+
'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {',
67+
Template.indent([
68+
`var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`,
69+
`var fullhref = ${RuntimeGlobals.publicPath} + href;`,
70+
'var existingLinkTags = document.getElementsByTagName("link");',
71+
'for(var i = 0; i < existingLinkTags.length; i++) {',
72+
Template.indent([
73+
'var tag = existingLinkTags[i];',
74+
'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");',
75+
'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return resolve();',
76+
]),
77+
'}',
78+
'var existingStyleTags = document.getElementsByTagName("style");',
79+
'for(var i = 0; i < existingStyleTags.length; i++) {',
80+
Template.indent([
81+
'var tag = existingStyleTags[i];',
82+
'var dataHref = tag.getAttribute("data-href");',
83+
'if(dataHref === href || dataHref === fullhref) return resolve();',
84+
]),
85+
'}',
86+
'var linkTag = document.createElement("link");',
87+
'linkTag.rel = "stylesheet";',
88+
'linkTag.type = "text/css";',
89+
'linkTag.onload = resolve;',
90+
'linkTag.onerror = function(event) {',
91+
Template.indent([
92+
'var request = event && event.target && event.target.src || fullhref;',
93+
'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + request + ")");',
94+
'err.code = "CSS_CHUNK_LOAD_FAILED";',
95+
'err.request = request;',
96+
'delete installedCssChunks[chunkId]',
97+
'linkTag.parentNode.removeChild(linkTag)',
98+
'reject(err);',
99+
]),
100+
'};',
101+
'linkTag.href = fullhref;',
102+
crossOriginLoading
103+
? Template.asString([
104+
`if (linkTag.href.indexOf(window.location.origin + '/') !== 0) {`,
105+
Template.indent(
106+
`linkTag.crossOrigin = ${JSON.stringify(
107+
crossOriginLoading
108+
)};`
109+
),
110+
'}',
111+
])
112+
: '',
113+
'var head = document.getElementsByTagName("head")[0];',
114+
'head.appendChild(linkTag);',
115+
]),
116+
'}).then(function() {',
117+
Template.indent(['installedCssChunks[chunkId] = 0;']),
118+
'}));',
119+
]),
120+
'}',
121+
])};`,
122+
])
123+
: '// no chunk loading',
124+
]);
125+
}
126+
};

0 commit comments

Comments
 (0)