Open arieltlm opened 3 years ago
import CSSSplitWebpackPlugin from 'css-split-webpack-plugin';
import { RawSource } from 'webpack-sources';
const isCSS = name => (/\.css$/).test(name);
const strip = str => str.replace(/\/$/, '');
export default class CSSSplitWebpackPluginFix extends CSSSplitWebpackPlugin {
constructor(options) {
super(options);
}
apply = compiler => {
if (this.options.defer) {
compiler.hooks.emit.tapAsync('CSSSplitWebpackPlugin', (compilation, callback) => {
return this.chunksMapping(compilation, compilation.chunks, callback);
});
} else {
compiler.hooks.thisCompilation.tap('CSSSplitWebpackPlugin', compilation => {
compilation.hooks.optimizeChunkAssets.tapAsync(
'CSSSplitWebpackPlugin',
(chunks, callback) => this.chunksMapping(compilation, chunks, callback)
);
});
}
}
chunksMapping(compilation, chunks, done) {
const { assets } = compilation;
const publicPath = strip(compilation.options.output.publicPath || './');
const promises = chunks.map(chunk => {
const input = chunk.files.filter(isCSS);
const items = input.map(name => this.file(name, assets[name]));
return Promise.all(items).then(entries => {
entries.forEach(entry => {
if (entry.chunks.length === 1) {
return;
}
// Inject the new files into the chunk.
entry.chunks.forEach(file => {
assets[file.name] = file;
chunk.files.add(file.name);
});
const content = entry.chunks.map(file => {
return `@import "${publicPath}/${file._name}";`;
}).join('\n');
const imports = this.options.imports({
...entry,
content,
});
if (!this.options.preserve) {
chunk.files.delete(entry.file);
delete assets[entry.file];
}
if (imports) {
assets[imports] = new RawSource(content);
chunk.files.add(imports);
}
});
return Promise.resolve();
});
});
Promise.all(promises).then(() => {
done();
}, done);
}
}
It is unnecessary to implement chunksMapping again, and here is my workaround:
const name = 'CSSSplitWebpackPluginFix';
const CSSSplitWebpackPlugin = require('css-split-webpack-plugin').default;
module.exports = class CSSSplitWebpackPluginFix extends CSSSplitWebpackPlugin {
apply(compiler) {
return super.apply(this.patchCompiler(compiler));
}
chunksMapping(compilation, chunks, done) {
return super.chunksMapping(compilation, this.patchChunks(chunks), done);
}
patchCompiler(compiler) {
// break 1: since that `compiler.plugin` has been removed
compiler.plugin = (hookName, hooker) => {
({
'emit' : () => compiler.hooks['emit'].tapAsync(name, hooker),
'this-compilation' : () => compiler.hooks['thisCompilation'].tap(name, compilation =>
hooker(this.patchCompilation(compilation))),
})[hookName]();
};
return compiler;
}
patchCompilation(compilation) {
// break 2: since that `compilation.plugin` has been removed
compilation.plugin = (hookName, hooker) => {
({
'optimize-chunk-assets' : () => compilation.hooks['processAssets'].tapAsync({
name, stage : compilation.constructor['PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT'],
}, (assets, done) => hooker(compilation['chunks'], done)),
})[hookName]();
};
return compilation;
}
patchChunks(chunks) {
// break 3: since that `chunk.files` has been changed from Array to Set
chunks.forEach(chunk => { chunk.files = Array.from(chunk.files) });
return chunks;
}
};
compiler.plugin is not a function, compiler.plugin api was removed in webpack@5