Технологические рамки и немного базы
Сразу оговорюсь, что приложение должно представлять собой PWA, чтобы его можно было использовать на любой платформе (веб, iOS, Android) без нативной реализации отдельного приложения под каждую из них. В качестве языка для серверной части был взят Python и его фреймворк Django. Для клиента же будем использовать JavaScript.
Не забываем, что рендеринг — это процесс преобразования кода приложения и пользовательских данных в готовые HTML-элементы, которые отображает веб-браузер конечного юзера. Определение же способа генерации и размещения данных HTML-страниц веб-приложения — это первоочередная задача еще на этапе проектирования архитектуры приложения. Она-то и требует детального анализа при поиске итогового решения. Последствия выбора — это сложность и скорость дальнейшей разработки, простота поддержки, эффективность продвижения и иные метрики.
Серверный рендеринг
Server-Side Rendering (SSR)
Серверный рендеринг (SSR) — это классическая модель рендеринга страниц веб-приложения, при которой полный HTML-документ формируется на стороне сервера в ответ на каждый пользовательский запрос. Термин SSR может использоваться для обозначения как всеобъемлющей концепции серверного рендеринга, так и конкретного подхода (который корректнее называть Dynamic SSR).
Основной механизм работы можно разбить на несколько пунктов:
- Пользовательский запрос. На данном этапе браузер клиента делает запрос на сервер для получения HTML-документа.
- Серверная обработка. Серверная логика, реализованная на Python Flask, Django, Node.js, и т. д., определяет данные, которые необходимы для запроса. Сервер заполняет соответствующий шаблон (файл *.html или *.jinja, если используется шаблонизатор Jinja) актуальными данными.
- Рендеринг. Здесь происходит последовательное выполнение кода шаблона шаблонизатором (например, Jinja, или любой другой, в том числе, написанный самостоятельно), при котором выполняются все циклы и условия внутри шаблона. По окончании данного процесса шаблонизатор генерирует полностью готовый статичный HTML-документ (строку), который веб-браузер может отобразить.
- Ответ.
На данном этапе сервер отправляет клиенту сгенерированный HTML-документ в ответе на его запрос. - Отображение в браузере и гидратация.
Браузер получает готовый HTML-документ и сразу его отображает. Зачастую, после отображения подгружаются и выполняются дополнительные JavaScript-файлы для реализации какой-то определенной пользовательской логики. Этот процесс называется «гидратацией», и мы рассмотрим его позднее.
”Выбор стратегии — это всегда компромисс. При проектировании каждого приложения необходимо учитывать все факторы ”
Static-Site Generation (SSG)
SSG — это подход серверного рендеринга, который предполагает предварительный рендеринг страниц на сервере (либо во время сборки) для каждого URL приложения, в отличие от генерации страниц в ответ на пользовательский запрос.

- Сборка и генерация страниц.
Запускается сборка приложения (например, npm run build), в процессе которой генерируются HTML-страницы приложения для каждого роута. Далее собранные статические файлы (HTML, CSS, JS) размещаются на CDN для дальнейшей доставки их клиенту. - Запрос от клиента. Когда браузер пользователя делает запрос на сервер (или CDN), сервер отдает уже готовый, заранее сгенерированный статический HTML-файл для указанной страницы. При этом в рантайме не происходит никакой работы сервера с данными.
Испытание нестабильным соединением
До этого мы сравнили оба подхода в идеальных условиях, когда нет сетевых задержек. Однако бывают ситуации, когда интернет-соединение нестабильно и нам важно знать, как будет вести себя приложение при таких вводных данных.

В случае использования какого-либо фронтенд-фреймворка в базовом сценарии после начальной и полной загрузки приложение работает по принципу SPA (Single Page Application). В этом случае при переходе по страницам не происходит полной перезагрузки приложения, потому что вся навигация была загружена на первом шаге. JavaScript подгружает только необходимые данные для роута и точечно обновляет DOM-дерево. При этом состояние приложения хранится в браузере пользователя.
Заключение
Время загрузки клиентских скриптов и время выполнения запроса для получения необходимых данных показано ниже в таблице:

В случае использования какого-либо фронтенд-фреймворка в базовом сценарии после начальной и полной загрузки приложение работает по принципу SPA (Single Page Application). В этом случае при переходе по страницам не происходит полной перезагрузки приложения, потому что вся навигация была загружена на первом шаге. JavaScript подгружает только необходимые данные для роута и точечно обновляет DOM-дерево. При этом состояние приложения хранится в браузере пользователя.
| Название ресурса | Тип (MIME) | Время (мс) |
| hybrid/ | text/html | 2132.20 |
| context_collector.js | text/javascript | 2038.62 |
| context_render.js | text/javascript | 2160.67 |
| context/?scope=[…] | application/json | 3659.74 |
Проведенный нами эксперимент наглядно показал: там, где Server Side Rendering обеспечивает монолитную стабильность макета и отсутствие сдвигов страницы впоследствии, он неизбежно проигрывает в скорости отклика при работе с тяжелыми данными либо в условиях медленного сетевого соединения. В то же время гибридный подход доказал свою эффективность в «борьбе за внимание» пользователя. Использование асинхронной загрузки данных и наличие прелоадеров позволило сократить параметр FCP до минимума. Это создает ощущение мгновенной работы даже при медленном интернет-соединении.