使用 webpack 加载的 css 时如何停止 FOUC

How to stop FOUC when using css loaded by webpack

我在使用 webpack 时在我的入口点内加载 css 时收到 FOUC。如果我从 webpack 加载中删除我的 css 并将其作为正常 link 包含在我的 html 文件中,那么 FOUC 的问题就会消失。

Note: This not just with bootstrap framework, I have tested with Foundation and Materialize with the same results

下面发布的代码只是我使用 Bootstrap.

问题的测试示例

Html代码

<!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 主入口点

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

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

我建议仅在生产环境中使用它,因为它会阻止热加载工作并使您的编译时间更长。我将 webpack.config.js 设置为仅在 process.env.NODE_ENV === "production" 时应用插件;当你在开发服务器上进行开发时,你仍然会得到 FOUC build/running,但我觉得这是一个公平的权衡。

有关如何设置的更多信息,请查看 SurviveJS's guide


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

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

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

聚会有点晚了,但我是这样做的。

虽然我认识到 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 }

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