Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webpack mini-css-extract-plugin => output multiple css-files on single entry

How can I setup webpack for my gutenberg blocks to extract multiple css files and bundle these based on the name of the stylesheets.

Zack Gordon used the Extract Text Plugin for this with webpack 3, and that worked like a charm. But with webpack 4 I had to switch to the mini-css-extract-plugin, in which I can't get this to work anymore.

See my current setup below, so you can see what I'm trying to do.

This is my project folder:

Plugin folder
|-- [src]
|   |-- [block1]
|   |   |-- block1.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   |-- [block2]
|   |   |-- block2.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   `-- index.js
`-- [build]
    |-- index.js
    |-- style.build.css
    `-- editor.build.css

In block1.js / block2.js:

import './style.scss'
import './editor.scss'

In index.js:

import './block1'
import './block2'

In webpack.config.js:

const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    ...defaultConfig,
    optimization: {
        ...defaultConfig.optimization,
        splitChunks: {
            cacheGroups: {
                style: {
                    name: 'style',
                    test: /style\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                },
                editor: {
                    name: 'editor',
                    test: /editor\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
    plugins: [
        ...defaultConfig.plugins,
        new MiniCssExtractPlugin({
            filename: 'blocks.[name].build.css'
            }),
    ],
    module: {
        ...defaultConfig.module,
        rules: [
            ...defaultConfig.module.rules,
            {
                test: /\.s?css$/,
                exclude: /node_modules/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ],
            },

        ]
    },
};

Expected output:

[build]
|-- blocks.editor.build.css
|-- index.js
|-- blocks.style.build.css

Current output:

[build]
|-- blocks.editor.build.css
|-- editor.js
|-- index.js
|-- blocks.style.build.css
|-- style.js
`-- (...and indentical map files)

The current setup spits out two extra js-files I don't need (style.js/editor.js), but the big problem is that it also causes the block not to load in Wordpress. It does load when I'm not using splitChunks, but then all css is bundled in a single file... and I need two.

Comparing: index.js without splitChunks:

/******/    // Load entry module and return exports
/******/    return __webpack_require__(__webpack_require__.s = "./src/index.js");
/******/ })

index.js with splitChunks:

/******/    // add entry module to deferred list
/******/    deferredModules.push(["./src/index.js","editor","style"]);
/******/    // run deferred modules when ready
/******/    return checkDeferredModules();
/******/ })
like image 813
Bornie Avatar asked Apr 14 '19 15:04

Bornie


People also ask

What does mini CSS extract plugin do?

This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps. It builds on top of a new webpack v5 feature and requires webpack 5 to work.

How do you minify CSS with Webpack?

To minify the resulting CSS, you'll use the optimize-css-assets-webpack-plugin: In Glitch console, run npm install --save-dev optimize-css-assets-webpack-plugin . Run refresh , so the changes are synchronized with the Glitch editor.

How does style loader work?

style-loader takes CSS you've imported in your JavaScript files, and injects them as <style></style> tags into the DOM. It's particularly useful for inlining Critical CSS into the <head> of your page.


1 Answers

See my comment, changed my setup and now it works: (OK, it's not a single entry anymore, but hey :-)

Project folder:

Plugin folder
|-- [src]
|   |-- [block1]
|   |   |-- block1.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   |-- [block2]
|   |   |-- block2.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   `-- index.js
|   `-- css.js
`-- [build]
    |-- index.js
    |-- style.build.css
    `-- editor.build.css

In css.js:

import './block1/style.scss'
import './block1/editor.scss'
import './block2/style.scss'
import './block2/editor.scss'

In webpack.config.js:

const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    ...defaultConfig,
    entry: {
        index: path.resolve( process.cwd(), 'src', 'index.js' ),
        css: path.resolve( process.cwd(), 'src', 'css.js' ),
    },
    optimization: {
        ...defaultConfig.optimization,
        splitChunks: {
            cacheGroups: {
                style: {
                    name: 'style',
                    test: /style\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                },
                editor: {
                    name: 'editor',
                    test: /editor\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
    plugins: [
        ...defaultConfig.plugins,
        new MiniCssExtractPlugin({
            filename: 'blocks.[name].build.css'
            }),
    ],
    module: {
        ...defaultConfig.module,
        rules: [
            ...defaultConfig.module.rules,
            {
                test: /\.s?css$/,
                exclude: /node_modules/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ],
            },

        ]
    },
};

Output build folder:

[build]
|-- blocks.editor.build.css
|-- index.js
|-- blocks.style.build.css
|-- style.js (ignore)
|-- editor.js (ignore)
|-- css.js (ignore)
`-- (...and indentical map files)
like image 192
Bornie Avatar answered Sep 16 '22 12:09

Bornie