โœ Handle CSS in webpack | Extract CSS

Francesco Di Donato - Aug 5 '20 - - Dev Community

These post is the second of a trilogy.

๐Ÿ”Ž Focus on ๐Ÿ–Œ CSS Handling Parts
(Index) #๏ธโƒฃ
development only inline CSS 1๏ธโƒฃ
both dev & prod mini-css-extract-plugin ๐Ÿ“Œ
production only CSS modules 3๏ธโƒฃ

Example Code ๐Ÿ“œ

webpack-extract-css


Final Product ๐Ÿค–

By completing this starge you will get a good starting point for your personal webpack configuration. In production mode it is better not to inject CSS directly into the bundle because you can get a Flash of Unstyled Content (FOUC) - the inlined CSS it's applied only when the bundle it's executed.
We implement the extraction of CSS in a separate file that is executed at the same time as the rest.


Flow of Thought ๐Ÿฎ

  1. Add build script
  2. Download the loader
  3. Create the loader function
  4. Connect to useRules
  5. Add the plugin in webpack.config.js

Implementation ๐Ÿค“

- 1 - Add build script

In packages.json add the build script that will bundle our code and store it in adist folder.

package.json
{
 ...
 "scripts": {
    "start": "webpack-dev-server --env development",
    "build": "webpack --env production"
  },
 ...
}
Enter fullscreen mode Exit fullscreen mode

- 2 - Download the loader

In the terminal invoke npm i -D mini-css-extract-plugin.

- 3 - Create the loader function

Add the package just downloaded in loaders.js. Then exports a new function named extractCSS - it's almost the sameto the one built in the first phase. The difference stays in the fact that style-loader is is replaced with MiniCssExtractPlugin.loader.

loaders.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// ... stage one created functions

exports.extractCSS = (config = {}) => {
    // basic rule
    const rule = {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
    };

    return addConfigs(rule, config);
};
Enter fullscreen mode Exit fullscreen mode

- 4 - Connect to useRules

In useRules the implementation is fair simple:

  1. import the just created function
  2. add its case in the loaders object
  3. add the instruction relative to production in instructions object ##### useRules.js
const { loadCSS, extractCSS } = require('./loaders'); //[1]

module.exports = (env) => {
    const loaders = {
        css: (i) => {
            switch (i) {
                case 'inline':
                    return loadCSS();
                case 'MCEP': //[2]
                    return extractCSS();
                default:
                    throw new Error(`The instruction ${i} is not covered`);
            }
        },
    };

    // developer interface
    const instructions = {
        css: {
            development: 'inline',
            production: 'MCEP', //[3] Mini-Css-Extract-Plugin
        },
    };

    // business logic - already seen in stage one
    let message = '[useRules] ';
    const rules = Object.entries(instructions).map(([key, value]) => {
        const i = instructions[key][env];
        message += key + '|' + i;
        return loaders[key](i);
    });

    console.info(message);
    return { rules };
};
Enter fullscreen mode Exit fullscreen mode

- 5 - Add the plugin in webpack.config.js

In order to properly work, MiniCssExtractPlugin need to be imported [1] and loaded [2] in the plugins section in webpack.config.js:

webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
 // [1]
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const useRules = require('./config/useRules');

module.exports = (env) => ({
    devServer: {
        open: true,
        stats: 'errors-only',
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Webpack Inline CSS',
        }),
      new MiniCssExtractPlugin({ // [2]
         filename: '[name].[hash].css'
      })
    ],
    module: useRules(env),
});
Enter fullscreen mode Exit fullscreen mode

Checking the Outcome ๐Ÿ˜Ž

  1. npm start: the web server will start and open up your bundle in a tab. Open devTools and peek in Network section. Reload the page. See? There is no trace of any CSS file - it is installed in the JavaScript.
  2. npm run build: a dist folder will be generated. Get into that and serve it cd dist && serve (you may need to npm i serve -g before). Now, the result is the same as before but open again the devTools, get in network. You see that? It's a separate CSS file. No more Flash of Unstyled Content!

In console you should see log such as [useRules] css|inline or [useRules] css|MCEP


Upgrade the last-stage ๐Ÿ”

avaiable soon

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player