Last active
January 26, 2024 20:20
-
-
Save kherock/69ecd01619c72b3b94806c46342ba8d8 to your computer and use it in GitHub Desktop.
Remove empty CSS modules workaround
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const EMPTY_MODULES_CLEANUP_DEP_TYPES = new Set([ | |
'harmony side effect evaluation', | |
'import()', | |
'single entry', | |
]); | |
class SetMap extends Map { | |
add (key, value) { | |
const set = this.get(key); | |
if (set === undefined) { | |
super.set(key, new Set([value])); | |
} else { | |
set.add(value); | |
} | |
} | |
} | |
/** | |
* Temporary workaround to clean up empty .js files left behind by | |
* mini-css-extract-plugin. This is already fixed in webpack@5. | |
* | |
* @see {@link https://github.com/webpack-contrib/mini-css-extract-plugin/issues/357} | |
*/ | |
module.exports = class MiniCssExtractPluginCleanup { | |
apply (compiler) { | |
compiler.hooks.thisCompilation.tap('mini-css-extract-plugin-cleanup', (compilation) => { | |
compilation.hooks.finishModules.tap('mini-css-extract-plugin-cleanup', (modules) => { | |
const toRemoveMap = new SetMap(); | |
for (const module of modules) { | |
if (module.type === 'css/mini-extract') { | |
for (const cssModuleReason of module.reasons) { | |
for (const reason of cssModuleReason.module.reasons) { | |
if (EMPTY_MODULES_CLEANUP_DEP_TYPES.has(reason.dependency.type)) { | |
toRemoveMap.add( | |
reason.module || cssModuleReason.module, | |
reason.dependency, | |
); | |
} | |
} | |
} | |
} | |
} | |
for (const [module, set] of toRemoveMap) { | |
// collapse transitive CSS module dependencies | |
module.dependencies = module.dependencies.flatMap(d => set.has(d) ? d.module.dependencies : [d]); | |
} | |
}); | |
compilation.hooks.optimizeChunkAssets.tapAsync('mini-css-extract-plugin-cleanup', (chunks, callback) => { | |
for (const chunk of chunks) { | |
if (!chunk.getModules().some(module => /^javascript\/(auto|cjs|esm)$/.test(module.type))) { | |
// chunk doesn't contain actual JS code, remove the file | |
const chunkJs = chunk.files.find(file => /\.js$/.test(file)); | |
if (!chunk.hasRuntime()) { | |
// this is a split chunk, merge it into the runtime chunks that depend on it | |
for (const group of compilation.chunkGroups) { | |
if (chunk.isInGroup(group)) { | |
const runtimeJs = group.runtimeChunk.files.find(file => /\.js$/.test(file)); | |
compilation.assets[runtimeJs]._source.add(compilation.assets[chunkJs]); | |
} | |
} | |
} | |
chunk.files = chunk.files.filter(file => { | |
if (/\.js(\.map)?$/.test(file)) { | |
delete compilation.assets[file]; | |
return false; | |
} | |
return true; | |
}); | |
} | |
} | |
callback(); | |
}); | |
}); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment