Если процесс frontend разработки привёл вас к вопросу SEO оптимизации, то почти наверняка, вы столкнётесь с понятием Server Side Rendering (SSR) и тесно связанной с ним гидратацией (или регидратацией). Представленная ниже информация является переводом в очень свободной форме и дополненным некоторыми особенностями, с целью прояснить subject.




Рассвет одностраничных приложений SPA


Модель одностраничных приложений The Single Page Application (SPA) набрала высокую популярность за последние несколько лет. Оно и понятно, этот подход даёт определённый профит по скорости, качеству обслуживания и создаёт основу для новых паттернов клиентской веб-разработки.

Как все, я думаю, прекрасно знают, SPA работает внутри браузера и не требует перезагрузки страницы во время использования.

Супер идея! Но, конечно, есть «подводные камни».

В числе самых распространённых случаев (если взять любой tutorial по react или vue) главная страница index.html содержит практически пустой HTML-файл с небольшим количеством глобальных для всего проекта ссылок CSS, JavaScript, шрифты и т.п.

И это проблема:

  • В процессе первоначальный рендеринг пользователю придётся ждать загрузки всей кодовой базы и всех ресурсов (конечно, есть исключения, и можно реализовать динамическую подгрузку так называемых js / css чанков, но это отдельная история)
  • Некоторые сканеры или парсеры, которые не умеют дожидаться подгрузки асинхронных запросов, просто увидят все страницы пустыми

Ну вы поняли:

<!DOCTYPE html>
<html>
<head>
  <title>My first SPA app</title>
  <script src="https://cdn_нашей_либы"></script>
</head>
<body>
  <div id="app"></div>

  <script>
    ...
    бла бла бла, регистрация приложения
    ...
  </script>
</body>
</html>

Рендеринг на стороне сервера SSR


В отличие от рендеринга на стороне клиента Client Side Rendering (CSR), который использует браузер для рендеринга всего содержимого приложения и получения данных с API и т.п., SSR использует… сервер. То есть, всё тот же рендеринг и получение данных обрабатывается сервером (NodeJS с помощью фреймворков Express, Next, Vue SSR, Nuxt или что там ещё...), а затем ответ с разметкой HTML, стилями, скриптами и полученными данными с API, отправляется браузеру.

Таким образом, вы можете использовать преимущества двух подходов: скорость / SEO и интерактивность / UX.

И так, всё же, что такое гидратация / регидратация?


Регидратация — это своего рода мост между SSR и CSR.

Существует такой показатель производительности веб страницы, как First Contentful Paint (FCP) — в приближённом переводе будет звучать как 'первая значимая отрисовка' — время, когда браузер начал отображать любой текст, изображения (включая фоновые). Это первые элементы, которые пользователь увидит на странице. Создав отчёт с помощью Lighthouse в Chrome, в закладке performance, вы сразу же увидите этот показатель.

Время, потраченное на генерацию содержимого на сервере и будет являться First Contentful Paint временем.

Сразу после этого, клиентский JavaScript начинает выполнение по созданию полноценного клиентского приложения (в большинстве случаев популярных фреймворков — virtual dom и binding интерфейса управления им).

В этот момент нет необходимости заново рендерить весь DOM на клиенте, но необходимо добавить недостающие события, методы, а в некоторых случаях и элементы, которые не рендерились на сервере.

Именно этот процесс и называется гидратацией или регидратацией (hydration / re-hydration). Немного более подробное описание можно найти в Руководстве Vue SSR (которое также есть на русском языке), но, соответственно, с некоторыми особенностями конкретно этого фреймворка.

Производительность


А вот в этой части появляются некоторые проблемы. Регидратация имеет определённый недостаток — это время до взаимодействия или Time to Interactive, которое можно увидеть во всё том же, известном нам, Lighthouse Chrome. Даже если вы организовали всё идеально на стороне сервера и страница имеет быструю первую отрисовку содержимого, пользователь сможет с ней взаимодействовать только после CSR регидратации, которая иногда выполняется довольно медленно. Это большой минус в части UX.

Ещё один показатель Max Potential First Input Delay — задержка первого ввода (англ. First input delay, FID) — одна из метрик производительности веб-страниц, которая описывает время, прошедшее с момента, когда пользователь впервые начал взаимодействовать с веб-страницей, т.е. нажал на ссылку, кнопку или использует элемент управления на основе JavaScript, до момента, когда веб-браузер может ответить на данное взаимодействие (определение с сайта mozilla).

И время регидратации напрямую влияет на этот показатель. И чем больше компонентов и логики на вашей странице — тем стремительнее увеличивается этот показатель.

Одним из способов решения является lazy load для hydration.

Примером реализации подобного подхода на Vue SSR / NuxtJS является пакет vue-lazy-hydration (в npm репозитории), который реализует выполнение гидратации только в видимой части viewport браузера и «гидрирует» остальную часть только в случае скролла страницы. Рекомендации по использованию этого пакета были найдены также на хабре в tutorial Создаем интернет-магазин на Nuxt.js, за что автору AntonMoskalchenko хочу выразить отдельную благодарность. В его статье были достигнуты показатели Performance в Lighthouse Chrome равные 100%.