Мы создаем наш новый веб-сайт полностью на React и используем разделение кода и scss. Всякий раз, когда запрашивается новая страница, она сначала загружает необработанный HTML в браузер, а затем через долю секунды или около того появляется стиль css, похоже, проблема FOUC. Это ужасно, и нам нужно выяснить, как обеспечить загрузку CSS перед рендерингом компонента (ов). У кого-нибудь есть опыт с этим? Похоже, что в настоящее время в Интернете отсутствует информация об этой проблеме. В настоящее время у нас есть 10 блоков js, но только один main.XXXXXXX.css.
Спасибо за ответ, Эндрю, я использую приложение create-react-app, поэтому их связанная настройка webpack / babel, и я бы действительно предпочел не извлекать, если это возможно.
Вы пробовали использовать производственную сборку через npm run build? Он обработает CSS и сохранит его на build/static/css/main.xxxx.css. Этот файл можно кэшировать (если веб-сервер настроен правильно), поэтому браузер должен иметь возможность отображать его без некрасивой задержки. См .: survivaljs.com/webpack/styling/separating-css
Спасибо, Джереми, в конце своего вопроса я сказал, что в настоящее время у нас уже есть один файл main.xxxx.css. Наш конвейер будет автоматически развертывать оптимизированную производственную сборку при каждом нажатии на наши соответствующие ветви. У меня не было этой проблемы в предыдущей версии реакции, но мы не делали разбиение кода. Мне интересно, проблема ли это в разделении кода?






Если у вас когда-либо был только один файл 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'.
Большинство браузеров будут рендерить (рисовать), когда у них будет создано «дерево рендеринга», а «дерево рендеринга» будет содержать CSSOM (то есть всю информацию о стилях). Как только браузер встречает вызов для получения таблицы стилей, ему теперь нужна эта информация для успешного создания «дерева рендеринга» и начала рисования страницы.
Прежде чем стили будут загружены, браузер попытается проанализировать остальную часть HTML, включая теги сценария, создав таким образом свое «дерево содержимого», но он не должен начинать рисование, пока не завершит свое «дерево визуализации». Сценарии также останавливают создание «дерева содержимого», так что выбор сценария будет иметь приоритет. Но рисование не произойдет, пока таблица стилей не будет проанализирована. Вот связанная тема: stackoverflow.com/questions/34269416/…
Привет, @TimothyBeamish, у меня сложная настройка, как вы объяснили. Разделение кода с помощью react-loadable и SSR. Похоже, что некоторые из блоков css вводятся после инициализации приложения, что занимает секунду. Тем временем вы видите FOUC. Интересно, сталкивались ли вы когда-нибудь с этой проблемой? Попытка найти решение, не вставляя критический путь css. TIA.
@HarshanaAbeyaratne - с тех пор мы перешли на шаблон CSS-in-JS и используем для этого библиотеку Emotion. Это сделало жизнь намного проще, чище и последовательнее.
Если это не для вас путь, вам нужно найти способ извлечь весь CSS и загрузить его до загрузки приложения. Лучший способ сделать это последовательно - извлечь его в один файл CSS, а если нет, то иметь очень жесткое соглашение об именах для различных генерируемых файлов CSS, а затем найти способ их предварительной загрузки (заранее зная их имя: рука). Я не знаю, как этого добиться, но это общая стратегия.
Я могу придумать два варианта:
document.addEventListener("DOMContentLoaded", function(event) {
ReactDOM.render(
<App />,
document.getElementById('root')
);
});
Я считаю, что наилучшей практикой является то, что стили HTML, отображаемые компонентом ReactJS, должны вызываться в этом компоненте. Поэтому я предпочитаю вариант 1. Примечание: если файл css является глобальным файлом, вы можете рассмотреть возможность рефакторинга, чтобы внутри компонента были только стили компонента.
Вы знаете, почему это происходит?
Я думаю, что CSS слишком тяжелый, поэтому, несмотря на то, что он вызывается раньше в водопаде, он загружается дольше, чем скрипт.
Вы используете упаковщик, например webpack?