Как остановить FOUC при использовании css, загружаемого webpack

Я получаю FOUC при загрузке css внутри моей точки входа при использовании webpack. Если я удалю свой css из загружаемого webpack и просто включу его в свой html файл в качестве обычной ссылки, проблема с FOUC исчезнет.

Примечание. Это не только с базой бутстрапов, я протестировал ее с помощью Основы и материализуются с теми же результатами

Код, представленный ниже, является лишь тестовым примером моей проблемы с использованием 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' },
    ]
  }
};

Ответ 1

ExtractTextWebpackPlugin позволит вам выводить ваш CSS как отдельный файл, а не встраивать его в ваш пакет JS. Затем вы можете включить этот файл в свой HTML, который, как вы сказали, предотвращает появление неровного содержимого.

Я бы рекомендовал использовать это только в производственных средах, так как он перестает работать с горячей загрузкой и делает ваш компилятор более продолжительным. У меня есть webpack.config.js, чтобы применить плагин только к process.env.NODE_ENV === "production"; вы все равно получаете FOUC, когда работаете над созданием/запуском сервера dev, но я чувствую, что это справедливый компромисс.

Для получения дополнительной информации о том, как это установить, посмотрите SurviveJS guide.

Ответ 2

Это janky, но я обертываю ReactDom.render() в setTimeout() в моем корневом файле index.js.

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

Ответ 3

Немного поздно для вечеринки, но вот как я это делаю.

В то время как я признаю достоинства 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 }

Voila, вы ничего не видите, пока не загрузится все приложение.