30

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' },
    ]
  }
};
4

3 回答 3

27

ExtractTextWebpackPlugin将允许您将 CSS 输出为单独的文件,而不是将其嵌入到您的 JS 包中。然后,您可以将此文件包含在您的 HTML 中,正如您所说,这可以防止无样式内容的闪烁。

我建议只在生产环境中使用它,因为它会停止热加载并使您的编译时间更长。我webpack.config.js设置为仅在以下情况下应用插件process.env.NODE_ENV === "production";当您进行开发构建/运行开发服务器时,您仍然会获得 FOUC,但我觉得这是一个公平的权衡。

有关如何设置的更多信息,请查看SurviveJS 的指南


更新:如评论中所述,ExtractTextWebpackPlugin 现在已被mini-css-extract-plugin取代- 您应该改用它。

于 2016-04-06T15:40:28.633 回答
12

派对有点晚了,但这是我的做法。

虽然我认识到 extract-text-plugin 的优点,但它受到一个重建错误的困扰,该错误会打乱 css 顺序,并且设置起来很痛苦。并且在 js 中设置超时不是任何人都应该做的事情(它很难看,并且不能保证 100% 防止 fouc)......

所以我的 index.html 是:

<!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>

然后,在最后的 client.js 中添加:

include "./unhide.css";

...并且 unhide.css 包含一行:

#app { display: block }

瞧,在加载整个应用程序之前,您什么都看不到。

于 2018-01-25T12:03:01.607 回答
3

它很笨拙,但我将 ReactDom.render() 包装在我的根 index.js 文件中的 setTimeout() 中。

setTimeout(ReactDOM.render(...), 0)

于 2017-05-10T21:04:59.603 回答