Skip to content

compiler.plugin is not a function,in wepack5 #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
arieltlm opened this issue Dec 1, 2020 · 2 comments
Open

compiler.plugin is not a function,in wepack5 #32

arieltlm opened this issue Dec 1, 2020 · 2 comments

Comments

@arieltlm
Copy link

arieltlm commented Dec 1, 2020

compiler.plugin is not a function,
compiler.plugin api was removed in webpack@5

@finalcat
Copy link

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);
    }
}

@aleen42
Copy link

aleen42 commented Aug 11, 2021

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;
    }
};

This was referenced Aug 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants