Skip to content

Commit efaf2e1

Browse files
committed
refactor: give a chance to modify the css href
give a chance to modify the css href by "mainTemplate.hooks.localVars" for another css resource manager
1 parent a78b301 commit efaf2e1

File tree

1 file changed

+128
-109
lines changed

1 file changed

+128
-109
lines changed

src/index.js

Lines changed: 128 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import webpack from 'webpack';
55
import sources from 'webpack-sources';
66

77
const { ConcatSource, SourceMapSource, OriginalSource } = sources;
8-
const { Template, util: { createHash } } = webpack;
8+
const {
9+
Template,
10+
util: { createHash },
11+
} = webpack;
912

1013
const NS = path.dirname(fs.realpathSync(__filename));
1114

@@ -97,7 +100,12 @@ class CssModule extends webpack.Module {
97100
}
98101

99102
class CssModuleFactory {
100-
create({ dependencies: [dependency] }, callback) {
103+
create(
104+
{
105+
dependencies: [dependency],
106+
},
107+
callback
108+
) {
101109
callback(null, new CssModule(dependency));
102110
}
103111
}
@@ -107,6 +115,8 @@ class MiniCssExtractPlugin {
107115
this.options = Object.assign(
108116
{
109117
filename: '[name].css',
118+
checkCssChunk: true,
119+
forceHookRuntime: false,
110120
},
111121
options
112122
);
@@ -241,9 +251,60 @@ class MiniCssExtractPlugin {
241251
.substring(0, hashDigestLength);
242252
});
243253
const { mainTemplate } = compilation;
244-
mainTemplate.hooks.localVars.tap(pluginName, (source, chunk) => {
254+
mainTemplate.hooks.localVars.tap(pluginName, (source, chunk, hash) => {
245255
const chunkMap = this.getCssChunkObject(chunk);
246-
if (Object.keys(chunkMap).length > 0) {
256+
if (this.options.forceHookRuntime || Object.keys(chunkMap).length > 0) {
257+
const chunkMaps = chunk.getChunkMaps();
258+
const linkHrefPath = mainTemplate.getAssetPath(
259+
JSON.stringify(this.options.chunkFilename),
260+
{
261+
hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
262+
hashWithLength: (length) =>
263+
`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
264+
chunk: {
265+
id: '" + chunkId + "',
266+
hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
267+
hashWithLength(length) {
268+
const shortChunkHashMap = Object.create(null);
269+
for (const chunkId of Object.keys(chunkMaps.hash)) {
270+
if (typeof chunkMaps.hash[chunkId] === 'string') {
271+
shortChunkHashMap[chunkId] = chunkMaps.hash[
272+
chunkId
273+
].substring(0, length);
274+
}
275+
}
276+
return `" + ${JSON.stringify(
277+
shortChunkHashMap
278+
)}[chunkId] + "`;
279+
},
280+
contentHash: {
281+
[NS]: `" + ${JSON.stringify(
282+
chunkMaps.contentHash[NS]
283+
)}[chunkId] + "`,
284+
},
285+
contentHashWithLength: {
286+
[NS]: (length) => {
287+
const shortContentHashMap = {};
288+
const contentHash = chunkMaps.contentHash[NS];
289+
for (const chunkId of Object.keys(contentHash)) {
290+
if (typeof contentHash[chunkId] === 'string') {
291+
shortContentHashMap[chunkId] = contentHash[
292+
chunkId
293+
].substring(0, length);
294+
}
295+
}
296+
return `" + ${JSON.stringify(
297+
shortContentHashMap
298+
)}[chunkId] + "`;
299+
},
300+
},
301+
name: `" + (${JSON.stringify(
302+
chunkMaps.name
303+
)}[chunkId]||chunkId) + "`,
304+
},
305+
contentHashType: NS,
306+
}
307+
);
247308
return Template.asString([
248309
source,
249310
'',
@@ -253,120 +314,78 @@ class MiniCssExtractPlugin {
253314
chunk.ids.map((id) => `${JSON.stringify(id)}: 0`).join(',\n')
254315
),
255316
'}',
317+
'',
318+
'function cssLinkHref(chunkId) {',
319+
Template.indent([
320+
`var href = ${linkHrefPath};`,
321+
`var fullhref = ${mainTemplate.requireFn}.p + href;`,
322+
'return {href: href, fullhref: fullhref};',
323+
]),
324+
'}',
256325
]);
257326
}
258327
return source;
259328
});
260-
mainTemplate.hooks.requireEnsure.tap(
261-
pluginName,
262-
(source, chunk, hash) => {
263-
const chunkMap = this.getCssChunkObject(chunk);
264-
if (Object.keys(chunkMap).length > 0) {
265-
const chunkMaps = chunk.getChunkMaps();
266-
const linkHrefPath = mainTemplate.getAssetPath(
267-
JSON.stringify(this.options.chunkFilename),
268-
{
269-
hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
270-
hashWithLength: (length) =>
271-
`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`,
272-
chunk: {
273-
id: '" + chunkId + "',
274-
hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
275-
hashWithLength(length) {
276-
const shortChunkHashMap = Object.create(null);
277-
for (const chunkId of Object.keys(chunkMaps.hash)) {
278-
if (typeof chunkMaps.hash[chunkId] === 'string') {
279-
shortChunkHashMap[chunkId] = chunkMaps.hash[
280-
chunkId
281-
].substring(0, length);
282-
}
283-
}
284-
return `" + ${JSON.stringify(
285-
shortChunkHashMap
286-
)}[chunkId] + "`;
287-
},
288-
contentHash: {
289-
[NS]: `" + ${JSON.stringify(
290-
chunkMaps.contentHash[NS]
291-
)}[chunkId] + "`,
292-
},
293-
contentHashWithLength: {
294-
[NS]: (length) => {
295-
const shortContentHashMap = {};
296-
const contentHash = chunkMaps.contentHash[NS];
297-
for (const chunkId of Object.keys(contentHash)) {
298-
if (typeof contentHash[chunkId] === 'string') {
299-
shortContentHashMap[chunkId] = contentHash[
300-
chunkId
301-
].substring(0, length);
302-
}
303-
}
304-
return `" + ${JSON.stringify(
305-
shortContentHashMap
306-
)}[chunkId] + "`;
307-
},
308-
},
309-
name: `" + (${JSON.stringify(
310-
chunkMaps.name
311-
)}[chunkId]||chunkId) + "`,
312-
},
313-
contentHashType: NS,
314-
}
315-
);
316-
return Template.asString([
317-
source,
318-
'',
319-
`// ${pluginName} CSS loading`,
320-
`var cssChunks = ${JSON.stringify(chunkMap)};`,
321-
'if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);',
322-
'else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {',
329+
mainTemplate.hooks.requireEnsure.tap(pluginName, (source, chunk) => {
330+
const chunkMap = this.getCssChunkObject(chunk);
331+
if (this.options.forceHookRuntime || Object.keys(chunkMap).length > 0) {
332+
const checkCssChunk = this.options.checkCssChunk;
333+
return Template.asString([
334+
source,
335+
'',
336+
`// ${pluginName} CSS loading`,
337+
checkCssChunk ? `var cssChunks = ${JSON.stringify(chunkMap)};` : '',
338+
'if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);',
339+
`else if(installedCssChunks[chunkId] !== 0${
340+
checkCssChunk ? ' && cssChunks[chunkId]' : ''
341+
}) {`,
342+
Template.indent([
343+
'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {',
323344
Template.indent([
324-
'promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {',
345+
'var hrefData = cssLinkHref(chunkId);',
346+
'var href = hrefData.href;',
347+
'var fullhref = hrefData.fullhref;',
348+
'var existingLinkTags = document.getElementsByTagName("link");',
349+
'for(var i = 0; i < existingLinkTags.length; i++) {',
350+
Template.indent([
351+
'var tag = existingLinkTags[i];',
352+
'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");',
353+
'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return resolve();',
354+
]),
355+
'}',
356+
'var existingStyleTags = document.getElementsByTagName("style");',
357+
'for(var i = 0; i < existingStyleTags.length; i++) {',
325358
Template.indent([
326-
`var href = ${linkHrefPath};`,
327-
`var fullhref = ${mainTemplate.requireFn}.p + href;`,
328-
'var existingLinkTags = document.getElementsByTagName("link");',
329-
'for(var i = 0; i < existingLinkTags.length; i++) {',
330-
Template.indent([
331-
'var tag = existingLinkTags[i];',
332-
'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");',
333-
'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return resolve();',
334-
]),
335-
'}',
336-
'var existingStyleTags = document.getElementsByTagName("style");',
337-
'for(var i = 0; i < existingStyleTags.length; i++) {',
338-
Template.indent([
339-
'var tag = existingStyleTags[i];',
340-
'var dataHref = tag.getAttribute("data-href");',
341-
'if(dataHref === href || dataHref === fullhref) return resolve();',
342-
]),
343-
'}',
344-
'var linkTag = document.createElement("link");',
345-
'linkTag.rel = "stylesheet";',
346-
'linkTag.type = "text/css";',
347-
'linkTag.onload = resolve;',
348-
'linkTag.onerror = function(event) {',
349-
Template.indent([
350-
'var request = event && event.target && event.target.src || fullhref;',
351-
'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + request + ")");',
352-
'err.request = request;',
353-
'reject(err);',
354-
]),
355-
'};',
356-
'linkTag.href = fullhref;',
357-
'var head = document.getElementsByTagName("head")[0];',
358-
'head.appendChild(linkTag);',
359+
'var tag = existingStyleTags[i];',
360+
'var dataHref = tag.getAttribute("data-href");',
361+
'if(dataHref === href || dataHref === fullhref) return resolve();',
359362
]),
360-
'}).then(function() {',
361-
Template.indent(['installedCssChunks[chunkId] = 0;']),
362-
'}));',
363+
'}',
364+
'var linkTag = document.createElement("link");',
365+
'linkTag.rel = "stylesheet";',
366+
'linkTag.type = "text/css";',
367+
'linkTag.onload = resolve;',
368+
'linkTag.onerror = function(event) {',
369+
Template.indent([
370+
'var request = event && event.target && event.target.src || fullhref;',
371+
'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + request + ")");',
372+
'err.request = request;',
373+
'reject(err);',
374+
]),
375+
'};',
376+
'linkTag.href = fullhref;',
377+
'var head = document.getElementsByTagName("head")[0];',
378+
'head.appendChild(linkTag);',
363379
]),
364-
'}',
365-
]);
366-
}
367-
return source;
380+
'}).then(function() {',
381+
Template.indent(['installedCssChunks[chunkId] = 0;']),
382+
'}));',
383+
]),
384+
'}',
385+
]);
368386
}
369-
);
387+
return source;
388+
});
370389
});
371390
}
372391

0 commit comments

Comments
 (0)