Сегодня я предлагаю отправиться в короткое, но интересное путешествие в прошлое. Мысленно и мгновенно телепортируемся в начало 00-х годов этого века и плавно вернемся в текущее время, пройдя все основные вехи фронтенд-инжиниринга. Такая ретроспектива полезна, чтобы понимать почему все именно так, зачем нужен BFF и почему мы вообще должны возиться с серверными компонентами. Итак, телепортируемся.
Статическая генерация страниц
В далекие-далекие времена наш родной JS был довольно забавной игрушкой, с помощью которой можно было затащить на страницу больше уязвимостей и багов, чем интерактивности и пользы. В те времена выражение веб-приложение было диковинкой. Все строили сайты.
Под капотом это был какой-нибудь MVC-фреймворк, где сущности разделялись по зонам ответственности, но существовали рядом в довольно жестком зацеплении. Весь контент генерировался на сервере и отправлялся в браузер пользователя в виде готовых HTML-страниц. Быстро и надежно.
Но недостатков было больше:
- Каждое действие приводило к полной перезагрузке страницы
- Масштабируемость решений была сомнительной, ведь такие приложения были монолитами
- Жесткий вендор-лок и на фронтенде и бэкенде, потому что приложения такого типа обычно строили на фреймворках, которые уже включали в себя весь необходимый тулинг
И, конечно, мириться с этим было нельзя, поэтому произошел акт эволюции.
Single Page Applications (SPA)
В 10-х годах начали активно развиваться фронтенд-фреймворки, с которыми мы работаем до сих пор. Первые версии React и ему подобных библиотек и фреймворков сильно продвинули нашу индустрию вперед. С их помощью веб-инжиниринг получил возможность отделить фронтенд от бэкенда. И на этом этапе и появилась профессия фронтенд-инженера.
Интерактивность приложений выросла многократно. Взаимодействия перестали приводить к обязательной перезагрузке страниц. Чаще всего пользователь лишь единожды за сессию загружал пустой HTML и дальше наслаждался уже плавным интерфейсом, потому что его содержанием управлял код, который был подгружен при парсинге этой единственной страницы.
По сути совершился переход от тонких клиентов к толстым.
О недостатках такого подхода мы все знаем уже на своем опыте:
- Страница загружается долго, до первой интерактивности могут пройти секунды
- Плохое SEO, потому что страница, которую парсят роботы пуста (весь контент создается в браузере пользователя)
- Огромные куски JS, которые необходимы, чтобы пользователь увидел хоть что-то
Backend For Frontend (BFF)
И, кажется, можно бы заняться решением описанных проблем SPA. Но до этого нужно было уделить внимание более важной задаче.
Кажется, что в 2015 году смартфон с выходом в интернет был уже у каждого экономически активного гражданина развитого мира. Оказалось, что большинству людей гораздо удобнее пользоваться приложениями с мобильных устройств. И не через браузер, а через мобильные приложения.
И все бы ничего, но мобильные приложения строятся немного иначе, чем веб-приложения. Соответственно, у них могут быть свои пожелания к тому виду и формату, в котором бэкенд присылает данные. Можно было бы усложнить бэкенд и заставить его приводить данные к тому виду, который запрашивает клиент, но поступили мудрее.
Бэкенд остался неизменным. Однако клиент стал ходить туда через прослойку-адаптер — Backend For Frontend (BFF), которая среди прочего и взяла на себя функцию форматирования данных под нужный формат.
Таким образом каждый фронтендер, работающий с BFF, отчасти стал фулстеком. Проблема решена, можно возвращаться к устранению недостатков SPA.
SSG, ISR, SSR
Первое очевидное решение — отменить весь прогресс и вернуться к статической генерации, но, желательно, сохранив современные, уже привычные инструменты для строительства страниц. Так и появился SSG (Static Site Generation) — подход, при котором страницы генерируются на сервере во время сборки приложения, складываются в какое-то хранилище и потом раздаются через CDN. При таком подходе мы снова потеряли интерактивность, но вернули скорость загрузки.
Развитием этой идеи стала технология инкрементальной регенерации — ISR (Incremental Static Regeneration). При таком подходе статические страницы создаются на сервере после запроса пользователя и хранятся в неизменном виде. Когда заданное время жизни (TTL — time to live) истекает, страница пересоздается в фоновом режиме, не требуя полной сборки проекта. Это довольно экономично и быстро, но все равно ещё недостаточно интерактивно.
SSR долгое время был венцом эволюции подходов рендеринга. При таком подходе мы генерируем заготовку страницы на сервере со всеми кнопками и формочками, после чего отправляем ее в браузер, приложив какое-то начальное состояние и инструкции о том, как сделать страницу интерактивной. Последнее называется гидрацией и тоже может занимать существенное время. Как итог, пользователь довольно быстро видит что-то помимо пустой HTML-страницы, но все равно вынужден дожидаться загрузки JS-кода, чтобы как-то с ней повзаимодействовать.
Уже лучше. Уже очень хорошо. Но есть еще один способ сделать отрисовку интерактивных страниц быстрее.
React Server Components (RSC)
5 декабря 2024 года состоялся релиз первой стабильной версии серверных компонентов React. Основная идея как будто вдохновлена ТРИЗ — нет компонента, нет проблемы. Суть подхода в том, чтобы не отправлять на клиент ничего, что не взаимодействует с браузером.
Проще говоря, рендеринг делится между сервером и клиентом.
Те сущности, которые ходят в БД, выглядят скорее статическими чем динамическими, не нуждаются во взаимодействии с браузерными API, исключаются из дерева компонентов и живут на сервере. Это серверные компоненты.
Клиентские компоненты помечаются директивой use client. Использовать её нужно вдумчиво, потому что отмеченные таким способом компоненты и все их поддерево попадает в бандл, который потом будет вынужден загрузить браузер.
Что же мы получили в итоге:
- быстрая гидрация, потому что компонентов, которые нужно «оживить» не так уж и много
- маленькие бандлы JS, так как они содержат только клиентский код
- повышенный уровень безопасности — чувствительный код может жить только на сервере
Ценой этого стала высокая когнитивная сложность разработки и отладки. Плюс сама технология достаточно свежа и сообщество еще не набило достаточного количества шишек. Ей предстоит еще долгое развитие.
Поэтому я бы советовал использовать такой подход только тогда, когда есть действительно высокая потребность в скорости загрузки. Давайте признаемся, она есть далеко не всегда.
Что же использовать в итоге?
Универсального ответа нет. У каждого подхода к рендерингу есть право на жизнь и кейсы, в которых он отрабатывает идеально, а так же есть те, в которых он делает проект невозможно плохим и с точки зрения бизнеса, и с точки зрения его поддержки и развития. Выбирайте с умом.







