Skip to content

Commit 74e0008

Browse files
committed
1 parent 7d1e0ca commit 74e0008

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

src/index.js

+70
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'path';
12
import webpack from 'webpack';
23
import sources from 'webpack-sources';
34

@@ -48,6 +49,7 @@ class CssModule extends webpack.Module {
4849
this.content = dependency.content;
4950
this.media = dependency.media;
5051
this.sourceMap = dependency.sourceMap;
52+
this.disconnectedGroups = {};
5153
}
5254

5355
// no source() so webpack doesn't do add stuff to the bundle
@@ -188,8 +190,76 @@ class MiniCssExtractPlugin {
188190
hash: chunk.contentHash[MODULE_TYPE],
189191
});
190192
}
193+
194+
const splitChunks = compilation.chunks.filter(chunk => {
195+
return (
196+
chunk.chunkReason && chunk.chunkReason.includes("split chunk")
197+
);
198+
});
199+
200+
splitChunks.forEach((splitChunk) => {
201+
const modulesWeCouldRemove = [];
202+
const nonCssModules = Array.from(splitChunk.modulesIterable).filter((mod) => {
203+
return mod.type !== MODULE_TYPE;
204+
});
205+
206+
nonCssModules.forEach((nonCssMod) => {
207+
if (
208+
nonCssMod._source &&
209+
nonCssMod._source._value === `// extracted by ${pluginName}`
210+
) {
211+
modulesWeCouldRemove.push(nonCssMod);
212+
}
213+
});
214+
215+
// If there's nothing but CSS modules left in this split chunk, remove the whole thing
216+
// This will mean that the main template manifest (ie. webpack's boilerplate code) won't
217+
// contain any references to these empty modules
218+
if (modulesWeCouldRemove.length === nonCssModules.length) {
219+
modulesWeCouldRemove.forEach((nonCssMod) => {
220+
// Trace all the "reasons" for this module (ie. other modules that depend on it)
221+
// then add this module into their respective chunks. This effectively reverses
222+
// the work SplitChunksPlugin did to break out the logic into a separate chunk.
223+
// Without this step there will be script errors owing to missing dependencies
224+
// and adding them back to their origin chunks is harmless as they're empty.
225+
nonCssMod.reasons.forEach((reason) => {
226+
reason.module.chunksIterable.forEach((previouslyConnectedChunk) => {
227+
splitChunk.moveModule(nonCssMod, previouslyConnectedChunk);
228+
});
229+
});
230+
});
231+
232+
splitChunk.groupsIterable.forEach((group) => {
233+
group.removeChunk(splitChunk);
234+
235+
// Book-keeping
236+
this.disconnectedGroups[splitChunk.id] =
237+
this.disconnectedGroups[splitChunk.id] || [];
238+
this.disconnectedGroups[splitChunk.id].push(group);
239+
});
240+
}
241+
});
191242
}
192243
);
244+
compilation.hooks.chunkAsset.tap(pluginName, (chunk, file) => {
245+
// If this was a split chunk we disconnected previously
246+
if (this.disconnectedGroups[chunk.id]) {
247+
if (path.extname(file) === '.css') {
248+
this.disconnectedGroups[chunk.id].forEach((group) => {
249+
// Add the stylesheet as a file on every chunk that requires it
250+
// This ensures plugins like html-webpack-plugin will find and include
251+
// split CSS chunks
252+
group.chunks.forEach((parentChunk) => {
253+
parentChunk.files.push(file);
254+
});
255+
});
256+
} else if (path.extname(file) === '.js') {
257+
// Discard empty JS file
258+
chunk.files.pop();
259+
delete compilation.assets[file];
260+
}
261+
}
262+
});
193263
compilation.chunkTemplate.hooks.renderManifest.tap(
194264
pluginName,
195265
(result, { chunk }) => {

0 commit comments

Comments
 (0)