Вы не выполняете рендеринг на стороне сервера, но все же хотите повысить производительность вашего сайта React? Попробуйте предварительный рендеринг!
react-snap
— это сторонняя библиотека, которая предварительно преобразует страницы вашего сайта в статические HTML-файлы. Это может сократить время первой отрисовки вашего приложения.
Вот сравнение одного и того же приложения с предварительным рендерингом и без него, загруженного на смоделированное соединение 3G и мобильное устройство:
Почему это полезно?
Основная проблема с производительностью больших одностраничных приложений заключается в том, что пользователю нужно дождаться завершения загрузки пакетов JavaScript, составляющих сайт, прежде чем он сможет увидеть какой-либо реальный контент. Чем больше пакеты, тем дольше пользователю придется ждать.
Чтобы решить эту проблему, многие разработчики используют подход к рендерингу приложения на сервере, а не только к его загрузке в браузере. При каждом переходе страницы/маршрута полный HTML-код генерируется на сервере и отправляется в браузер, что сокращает время первой отрисовки, но происходит за счет более медленного времени до первого байта.
Предварительный рендеринг — это отдельный метод, который менее сложен, чем серверный рендеринг, но также позволяет сократить время первой отрисовки в вашем приложении. Безголовый браузер или браузер без пользовательского интерфейса используется для создания статических HTML-файлов каждого маршрута во время сборки . Эти файлы затем можно отправить вместе с пакетами JavaScript, необходимыми для приложения.
реакция-привязка
react-snap
использует Puppeteer для создания предварительно обработанных HTML-файлов различных маршрутов в вашем приложении. Для начала установите его как зависимость разработки:
npm install --save-dev react-snap
Затем добавьте скрипт postbuild
в package.json
:
"scripts": {
//...
"postbuild": "react-snap"
}
Это будет автоматически запускать команду react-snap
каждый раз при создании новой сборки приложения ( npm build
).
Последнее, что вам нужно будет сделать, это изменить способ загрузки приложения. Измените файл src/index.js
на следующее:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
const rootElement = document.getElementById("root");
if (rootElement.hasChildNodes()) {
ReactDOM.hydrate(<App />, rootElement);
} else {
ReactDOM.render(<App />, rootElement);
}
Вместо использования ReactDOM.render
только для рендеринга корневого элемента React непосредственно в DOM, он проверяет, присутствуют ли уже какие-либо дочерние узлы, чтобы определить, было ли содержимое HTML предварительно отрисовано (или отрисовано на сервере). В этом случае вместо этого используется ReactDOM.hydrate
для подключения прослушивателей событий к уже созданному HTML вместо его создания заново.
При сборке приложения теперь будут генерироваться статические HTML-файлы в качестве полезных данных для каждого сканируемого маршрута. Вы можете посмотреть, как выглядит полезная нагрузка HTML, щелкнув URL-адрес HTML-запроса, а затем перейдя на вкладку «Предварительный просмотр» в Chrome DevTools.
Flash нестилизованного контента
Хотя статический HTML теперь отображается почти сразу, по умолчанию он по-прежнему остается без стиля, что может вызвать проблему с отображением «вспышки нестилизованного контента» (FOUC). Это может быть особенно заметно, если вы используете библиотеку CSS-in-JS для создания селекторов, поскольку пакет JavaScript должен завершить выполнение, прежде чем можно будет применить какие-либо стили.
Чтобы предотвратить это, критический CSS или минимальное количество CSS, необходимое для отображения начальной страницы, можно встроить непосредственно в <head>
HTML-документа. react-snap
использует под капотом еще одну стороннюю библиотеку, minimalcss
, для извлечения любого критического CSS для разных маршрутов. Вы можете включить это, указав следующее в файле package.json
:
"reactSnap": {
"inlineCss": true
}
Взглянув на предварительный просмотр ответа в Chrome DevTools, вы увидите стилизованную страницу с встроенным критическим CSS.
Заключение
Если вы не используете маршруты рендеринга на стороне сервера в своем приложении, используйте react-snap
для предварительной рендеринга статического HTML для ваших пользователей.
- Установите его как зависимость для разработки и начните с настроек по умолчанию.
- Используйте экспериментальную опцию
inlineCss
для встраивания критического CSS, если она подходит для вашего сайта. - Если вы используете разделение кода на уровне компонентов внутри каких-либо маршрутов, будьте осторожны и не визуализируйте предварительно состояние загрузки для своих пользователей. README
react-snap
описывает это более подробно.