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

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

Хуссейн Джирдех
Houssein Djirdeh

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

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

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

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

Основная проблема производительности больших одностраничных приложений заключается в том, что пользователю необходимо дождаться завершения загрузки пакета(ов) JavaScript, из которых состоит сайт, прежде чем он сможет увидеть какой-либо реальный контент. Чем больше пакеты, тем дольше пользователю придется ждать.

Чтобы решить эту проблему, многие разработчики используют подход рендеринга приложения на сервере вместо того, чтобы загружать его только в браузере. При каждом переходе страницы/маршрута полный HTML генерируется на сервере и отправляется в браузер, что сокращает время первой отрисовки, но приводит к более медленному времени до первого байта.

Предварительный рендеринг — это отдельная техника, которая менее сложна, чем серверный рендеринг, но также позволяет улучшить время первой отрисовки в вашем приложении. Headless-браузер или браузер без пользовательского интерфейса используется для генерации статических 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-запроса, а затем нажав вкладку Previews в Chrome DevTools.

Сравнение до и после. Снимок после показывает, что контент отрендерен.

Вспышка нестилизованного контента

Хотя статический 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 описывает это более подробно.