Reputation: 2957
I am getting FOUC when loading CSS inside of my entry point when using webpack
. If I remove my CSS from being loaded by webpack
and just include it in my HTML file as a normal link, then the problem with FOUC goes away.
Note: This not just with bootstrap framework, I have tested with Foundation and Materialize with the same results
The code posted below is just a test example of my problem using Bootstrap.
Html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Navbar example</h1>
</div>
</div> <!-- /container -->
<script src="build/bundle.js"></script>
</body>
</html>
bootstrap.js main entry point
import "../node_modules/bootstrap/dist/css/bootstrap.css";
import bootstrap from 'bootstrap'
$(document).ready(function () {
console.log('bootstrap loaded')
});
webpack.config.js
var path = require('path');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const webpack = require("webpack");
module.exports = {
entry: './src/bootstrap.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'bundle.js'
},
resolve: {
extensions: ['', '.js']
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
'window.jQuery': 'jquery'
})
],
devtool: 'inline-source-map',
module: {
resolve: {
modulesDirectories: ['node_modules']
},
loaders: [
{
test: path.join(__dirname, 'src'),
loader: 'babel-loader',
query: {
presets: ['es2015']
}
},
{ test: /\.css?$/, loader: 'style!css'},
{ test: /\.html$/, loader: 'html' },
{ test: /\.(png|gif|jpg)$/, loader: 'url', query: { limit: 8192 } },
{ test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url', query: { limit: 10000, mimetype: 'application/font-woff2' } },
{ test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url', query: { limit: 10000, mimetype: 'application/font-woff' } },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file' },
]
}
};
Upvotes: 31
Views: 14478
Reputation: 35797
ExtractTextWebpackPlugin will allow you to output your CSS as a separate file rather than having it embedded in your JS bundle. You can then include this file in your HTML, which as you said, prevents the flash of unstyled content.
I'd recommend only using this in production environments, as it stops hot-loading from working and makes your compile take longer. I have my webpack.config.js
set up to only apply the plugin when process.env.NODE_ENV === "production"
; you still get the FOUC when you're doing a development build/running the dev server, but I feel like this is a fair trade off.
For more information on how to set this up, take a look at SurviveJS's guide.
Update: As noted in the comments, ExtractTextWebpackPlugin has now been superceded by mini-css-extract-plugin - you should use that instead.
Upvotes: 28
Reputation: 131
A bit late to the party, but here's how I do it.
While I recognize the merits of extract-text-plugin, it's plagued by a rebuild bug that messes up css order, and is a pain to set up. And setting timeouts in js is not something anyone should be doing (it's ugly and is not guaranteed 100% to prevent fouc)...
So my index.html is:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style>
#app { display: none }
</style>
<title></title>
</head>
<body>
<div id="app"></div>
<script src="scripts/bundle.js"></script>
</body>
</html>
Then, in client.js at the very end I add:
include "./unhide.css";
...and unhide.css contains a single line:
#app { display: block }
Voila, you see nothing until the whole app is loaded.
Upvotes: 13
Reputation: 304
It's janky, but I wrap ReactDom.render() in a setTimeout() in my root index.js file.
setTimeout(ReactDOM.render(...), 0)
Upvotes: 4