Дождитесь загрузки CSS перед загрузкой JS в React [FOUC]

Мы создаем наш новый веб-сайт полностью на React и используем разделение кода и scss. Всякий раз, когда запрашивается новая страница, она сначала загружает необработанный HTML в браузер, а затем через долю секунды или около того появляется стиль css, похоже, проблема FOUC. Это ужасно, и нам нужно выяснить, как обеспечить загрузку CSS перед рендерингом компонента (ов). У кого-нибудь есть опыт с этим? Похоже, что в настоящее время в Интернете отсутствует информация об этой проблеме. В настоящее время у нас есть 10 блоков js, но только один main.XXXXXXX.css.

Вы используете упаковщик, например webpack?

Andrew 26.03.2018 20:19

Спасибо за ответ, Эндрю, я использую приложение create-react-app, поэтому их связанная настройка webpack / babel, и я бы действительно предпочел не извлекать, если это возможно.

Gregg 26.03.2018 20:44

Вы пробовали использовать производственную сборку через npm run build? Он обработает CSS и сохранит его на build/static/css/main.xxxx.css. Этот файл можно кэшировать (если веб-сервер настроен правильно), поэтому браузер должен иметь возможность отображать его без некрасивой задержки. См .: survivaljs.com/webpack/styling/separating-css

Jeremy 26.03.2018 22:56

Спасибо, Джереми, в конце своего вопроса я сказал, что в настоящее время у нас уже есть один файл main.xxxx.css. Наш конвейер будет автоматически развертывать оптимизированную производственную сборку при каждом нажатии на наши соответствующие ветви. У меня не было этой проблемы в предыдущей версии реакции, но мы не делали разбиение кода. Мне интересно, проблема ли это в разделении кода?

Gregg 26.03.2018 23:13
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
13
4
6 630
2

Ответы 2

Если у вас когда-либо был только один файл main.XXXXXXX.css, вам следует вручную вставить его в раздел <head> начального представления html и загрузить запись в свое приложение (также как исходный файл JS или какой-либо файл JS манифеста веб-пакета) внизу того же представления HTML.

Например

<html>
   <head>
      ...some header stuff
      <link type = "text/css" rel = "stylesheet" href = "/path/to/main.XXXXXXX.css">
   </head>
   <body>
      <div id = "react-app"></div>
      <script src = "/path/to/vendor.js"></script>
      <script src = "/path/to/app_entry_or_webpack_manifest.js"></script>
   <body>
</html>

Я предполагаю, что у вас есть сервер, обслуживающий по крайней мере страницу, похожую на приведенную выше. В этом случае (см. Выше) ваш CSS загрузится раньше JS, и вам следует избегать проблемы с FOUC.

Эта проблема становится намного сложнее, если у вас есть много файлов css, динамически генерируемых (посредством разделения кода), когда вы разбиваете свое приложение на части, но похоже, что у вас еще нет этой проблемы.

Обновлено: только что понял, что вы, возможно, не знаете, как вставить динамически созданный лист css в свой входной html файл. Если вы используете плагин mini-css-extract, вы можете указать создаваемое им имя файла. В этом примере вы можете видеть, что вы можете дополнительно включить [хеш] или нет. Наверное, вам не нужен хеш.

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production'

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      }
    ]
  }
}

Наличие стилей в <head> не гарантирует, что они будут проанализированы до того, как <script> находится в <body>, даже с rel='preload'.

zurfyx 21.10.2018 17:54

Большинство браузеров будут рендерить (рисовать), когда у них будет создано «дерево рендеринга», а «дерево рендеринга» будет содержать CSSOM (то есть всю информацию о стилях). Как только браузер встречает вызов для получения таблицы стилей, ему теперь нужна эта информация для успешного создания «дерева рендеринга» и начала рисования страницы.

Timothy Beamish 18.11.2019 01:02

Прежде чем стили будут загружены, браузер попытается проанализировать остальную часть HTML, включая теги сценария, создав таким образом свое «дерево содержимого», но он не должен начинать рисование, пока не завершит свое «дерево визуализации». Сценарии также останавливают создание «дерева содержимого», так что выбор сценария будет иметь приоритет. Но рисование не произойдет, пока таблица стилей не будет проанализирована. Вот связанная тема: stackoverflow.com/questions/34269416/…

Timothy Beamish 18.11.2019 01:06

Привет, @TimothyBeamish, у меня сложная настройка, как вы объяснили. Разделение кода с помощью react-loadable и SSR. Похоже, что некоторые из блоков css вводятся после инициализации приложения, что занимает секунду. Тем временем вы видите FOUC. Интересно, сталкивались ли вы когда-нибудь с этой проблемой? Попытка найти решение, не вставляя критический путь css. TIA.

Harshana 14.10.2020 15:20

@HarshanaAbeyaratne - с тех пор мы перешли на шаблон CSS-in-JS и используем для этого библиотеку Emotion. Это сделало жизнь намного проще, чище и последовательнее.

Timothy Beamish 27.11.2020 22:34

Если это не для вас путь, вам нужно найти способ извлечь весь CSS и загрузить его до загрузки приложения. Лучший способ сделать это последовательно - извлечь его в один файл CSS, а если нет, то иметь очень жесткое соглашение об именах для различных генерируемых файлов CSS, а затем найти способ их предварительной загрузки (заранее зная их имя: рука). Я не знаю, как этого добиться, но это общая стратегия.

Timothy Beamish 27.11.2020 22:34

Я могу придумать два варианта:

  1. Вызовите css внутри index.js вашего приложения для реагирования.
  2. Визуализируйте приложение реакции после загрузки DOM. Попробуйте добавить что-то подобное в свой файл реакции index.js:
    document.addEventListener("DOMContentLoaded", function(event) {
      ReactDOM.render(
        <App />,
        document.getElementById('root')
      );
    });

Я считаю, что наилучшей практикой является то, что стили HTML, отображаемые компонентом ReactJS, должны вызываться в этом компоненте. Поэтому я предпочитаю вариант 1. Примечание: если файл css является глобальным файлом, вы можете рассмотреть возможность рефакторинга, чтобы внутри компонента были только стили компонента.

Вы знаете, почему это происходит?

Vencovsky 24.05.2019 17:04

Я думаю, что CSS слишком тяжелый, поэтому, несмотря на то, что он вызывается раньше в водопаде, он загружается дольше, чем скрипт.

Nico Diz 24.05.2019 19:38

Другие вопросы по теме