2

I’m just learning webpack. As an exercise, I’ve used it to bundle Bootstrap. If I use the bundle with one of their basic examples, the Starter Template, I get a FOUC if I put <script src="./main.js"></script> at the end of the <body>. There’s no FOUC if I put it at the beginning of the <body>.

Should the <script> go at the beginning of the <body>? Or should it go at the end of the <body>, in which case some other method should be used to prevent the FOUC? For example, use mini-css-extract-plugin to create a separate CSS file rather than include it in the webpack JS bundle as described in other posts like this one.

Code

dist/index.html

Same as Starter Template | Bootstrap except

  • Remove the stylesheet <link> and JS <script> lines
  • Insert <script src="./main.js"></script>
    • At beggining of <body>: no FOUC
    • At end of <body>: FOUC

webpack.config.js

const path = require('path');

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.(scss)$/,
                use: [{
                    loader: 'style-loader', // inject CSS to page
                }, {
                    loader: 'css-loader', // translates CSS into CommonJS modules
                }, {
                    loader: 'postcss-loader', // Run postcss actions
                    options: {
                        plugins: function () { // postcss plugins, can be exported to postcss.config.js
                            return [
                                require('autoprefixer')
                            ];
                        }
                    }
                }, {
                    loader: 'sass-loader' // compiles Sass to CSS
                }]
            }
        ]
    }
};

src/index.js

import 'bootstrap';
import './scss/index.scss';

src/scss/index.scss

@import "~bootstrap/scss/bootstrap";
@import "custom";

Where scss/_custom.scss is trivial.

Environment: webpack: 4.44, bootstrap: 4.4, Chrome: v80, Firefox: v78, Edge: v44 (these browsers all had a FOUC/no-FOUC as described above).

sfsacc
  • 61
  • 5

1 Answers1

1

I'll attempt to answer my own question. Because we don't want content to be delayed by scripts, in production <script src="./main.js"> should be inserted at the end of <body>. Also, to prevent a FOUC, in production the CSS should be extracted to main.css using mini-css-extract-plugin rather than be loaded dynamically from main.js.

In development, you may want to use style-loader instead of mini-css-extract-plugin. This loads CSS dynamically from main.js rather than create main.css. This allows you do things like hot module replacement. As mentioned in the [mini-css-extract-plugin repository (https://github.com/webpack-contrib/mini-css-extract-plugin):

[mini-css-extract-plugin] should be used only on production builds without style-loader in the loaders chain, especially if you want to have HMR in development.

The problem is that loading CSS dynamically causes a FOUC unless main.js is loaded at the beginning of <body>. If this doesn't bother you, then you can leave it at the end. I posted this example on Bitbucket that shows how the Bootstrap starter-template example can be compiled from source where main.js is automatically inserted at the beginning or end of <body> in development and production modes, respectively.

sfsacc
  • 61
  • 5
  • I've encountered the same problem, and also discovered that the FOUC only occurs when doing a dev build. Production builds, which use `mini-css-extract-plugin`, have no FOUC and feel great. – lance.dolan Oct 13 '21 at 20:11