Предварительный рендеринг маршрутов с помощью реакции-привязки

Вы не выполняете рендеринг на стороне сервера, но все же хотите повысить производительность вашего сайта React? Попробуйте предварительный рендеринг!

react-snap — это сторонняя библиотека, которая предварительно преобразует страницы вашего сайта в статические HTML-файлы. Это может сократить время первой отрисовки вашего приложения.

Вот сравнение одного и того же приложения с предварительным рендерингом и без него, загруженного на смоделированное соединение 3G и мобильное устройство:

Параллельное сравнение загрузки. Версия с предварительным рендерингом загружается на 4,2 секунды быстрее.

Почему это полезно?

Основная проблема с производительностью больших одностраничных приложений заключается в том, что пользователю нужно дождаться завершения загрузки пакетов 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.

Сравнение до и после. На снимке «После» показано, что контент отрендерен и стилизован благодаря встроенному критическому CSS.

Заключение

Если вы не используете маршруты рендеринга на стороне сервера в своем приложении, используйте react-snap для предварительной рендеринга статического HTML для ваших пользователей.

  1. Установите его как зависимость для разработки и начните с настроек по умолчанию.
  2. Используйте экспериментальную опцию inlineCss для встраивания критического CSS, если она подходит для вашего сайта.
  3. Если вы используете разделение кода на уровне компонентов внутри каких-либо маршрутов, будьте осторожны и не визуализируйте предварительно состояние загрузки для своих пользователей. README react-snap описывает это более подробно.