В современной веб-разработке SEO и производительность часто вступают в противоречие. SSR дает хорошую индексацию, но усложняет архитектуру. CSR быстрее в разработке и меньше нагружает сервер, но поисковые боты могут не понять страницу.
Мы разрабатываем продуктовый сайт на Angular 17 с микрофронтендовой архитектурой на Module Federation. Нам нужно было и хорошее SEO, и привычный CSR для пользователей. В итоге мы выбрали гибридный подход: для людей — клиентский рендеринг, для поисковых ботов — пререндеринг через доработанный сервис MTS botview.
В статье рассказываем, почему чистый SSR не подошел, как мы разделили рендеринг, что доработали в открытом решении и как отличаем ботов от людей без ошибок.
Для начала поясним, что такое SSR и CSR:
-
SSR (Server-Side Rendering) — метод рендеринга веб-страницы на сервере, где сервер отдает уже полностью сформированную HTML-страницу.
-
CSR (Client-Side Rendering) — метод рендеринга, при котором основной контент формируется непосредственно в браузере, а сервер отдает минимальный HTML-шаблон.
Что за проект и какие были требования
Сайт написан на Angular 17 с использованием микрофронтендовой архитектуры, которая реализована с помощью Module Federation из пакета @angular-architects. Это продуктовый сайт, поэтому для него важно быть в топе поисковой выдачи — то есть иметь хорошее SEO.
Изначально на сайте был реализован SSR, который позволяет отдавать браузеру практически готовый HTML-файл со структурным содержимым (тексты, ссылки, картинки). Это положительно влияет на SEO.
Однако в связи с архитектурными и техническими особенностями не было возможности сделать чистый SSR, который предлагает Angular «из коробки».
Почему чистый SSR не подошел
Для начала нужно понять архитектурные особенности и структуру сайта. У нас есть:
-
SSR;
-
микрофронтенды, реализованные с помощью динамического Module Federation;
-
каждый сервис находится в отдельном репозитории, разворачивается отдельно и подгружается только при непосредственном взаимодействии с ним (например, при переходе на страницу этого сервиса).
Основная причина отказа от SSR — обновление версии Angular с 12 до 17. В версиях 16–17 произошли крупные изменения, некоторые из них коснулись пакета для работы с SSR. Например, @nguniversal перестали поддерживать, а его функциональность перенесли в @angular/ssr
Была попытка перейти на Nx (инструмент для сборки), но в нем не поддерживается Dynamic Module Federation и SSR одновременно. Это вызвало трудности с сохранением архитектуры и способствовало переходу к разделению рендеринга.
Но раз чистый SSR отпал, нужно было искать альтернативу. И тут мы вспомнили про микрофронтенды — они тоже внесли свою лепту в сложность.
Module Federation и SSR: как соединяли
Изначально реализация строилась на двух библиотеках:
-
@nguniversal/common— для SSR; -
@angular-architects/module-federation— для Module Federation.
Соединить их в единую работающую схему оказалось нетривиальной задачей. Dynamic Module Federation подразумевает подгрузку модулей по требованию, а SSR в Nx требует, чтобы все маршруты и компоненты были известны на сервере заранее. Эти два подхода вступают в противоречие, что и стало одной из ключевых причин поиска альтернативы.
В итоге мы поняли: нужно либо полностью переписывать архитектуру, либо искать обходной путь. Мы выбрали второй вариант.
Какое решение выбрали: раздельный рендеринг для людей и ботов
Мы выбрали подход с разделением рендеринга для клиентов и поисковых ботов:
-
Для клиентов работает обычный CSR. Браузер получает практически пустую HTML-страницу, а уже при исполнении скриптов она наполняется контентом.
-
Для поисковых ботов реализован пререндеринг с помощью сервиса МТС botview, который позволяет отрендерить страницу перед отдачей ее боту.
Мы доработали открытое решение (увеличили производительность и скорость рендеринга, оптимизировали занимаемую память) и внедрили его в веб-сайт.
Как это работает: сервер по заголовку User-Agent определяет, кто запрашивает страницу — клиент или поисковый бот, — и перенаправляет исполнение на соответствующий сервис.
Логичный вопрос: а почему мы вообще решили, что для людей можно оставить CSR, а для ботов делать отдельный пререндеринг? Давайте сравним подходы.
Почему выбрали раздельный рендеринг, а не что-то другое
Если сравнивать CSR и SSR, ключевые различия выглядят так:
|
Характеристика |
CSR |
SSR |
|
Скорость первоначальной загрузки |
Ниже (ждем скрипты) |
Выше (готовый HTML) |
|
TBT (Total Blocking Time) |
Выше |
Ниже |
|
Нагрузка на сервер |
Ниже |
Выше |
|
SEO |
Хуже |
Лучше |
|
Удобство для SPA |
Привычнее |
Сложнее |
Проанализировав преимущества и недостатки двух подходов, мы решили для людей оставить простой CSR, а SEO-требования закрыть через пререндеринг для ботов. Это позволило:
-
не переписывать архитектуру под чистый SSR;
-
сохранить привычный CSR разработки;
-
гарантировать хорошую индексацию.
Выбор сделан, решение принято. Осталось самое интересное — доработать открытый сервис под наши задачи.
Что доработали в открытом решении (MTS botview)
Основные доработки касались производительности и размеров требуемой памяти:
-
Открытие внутреннего браузера один раз, а не для каждого запроса.
-
Закрытие окон отрендеренных страниц после использования.
-
Добавление метрик для мониторинга.
В результате мы сократили:
-
время рендеринга страницы;
-
объем памяти, который занимает рендеринг.
Это позволило обрабатывать больше запросов на том же железе и снизить задержки при индексации.
Но как бы хорошо ни работал пререндеринг, важно не ошибиться с тем, кому его отдавать. Ведь если бот получит пустую страницу — пострадает SEO. А если человек попадет на пререндеренную страницу — ничего страшного, но все же…
Как отличаем ботов от людей
Основной способ различить людей и ботов — заголовок User-Agent:
-
Для клиентов там обычно прописывается специфика браузера и устройства (Chrome, Firefox, Safari и т.д.).
-
Для ботов существует список известных значений: Googlebot, YandexBot, Bingbot и другие.
Что будет, если ошибемся?
-
Если человек попадет на пререндеринг — ничего страшного. Страница также загрузится, и пользователь сможет с ней взаимодействовать (просто получит готовый HTML вместо пустого шаблона).
-
Если поисковый бот получит непререндеренную страницу (CSR) — он может ее не распарсить и не понять, что на ней находится. Это приведет к падению позиций в выдаче.
Поэтому важно поддерживать актуальный список User-Agent для ботов и мониторить, не появляются ли новые.
Прежде чем остановиться на MTS botview, мы, конечно, рассматривали и другие варианты. Коротко расскажем, почему выбор пал именно на него.
Какие еще решения рассматривали и почему от них отказались
Мы пытались все-таки остаться в рамках чистого SSR + Dynamic Module Federation + раздельные репозитории. Но чтобы добиться хоть какого-то рабочего варианта, потребовалось бы много времени (которого у нас не было), и это был бы очень тяжелый технический вызов.
Почему выбрали именно MTS botview:
-
сервис оказался в открытом доступе;
-
он достаточно прост для понимания и доработок;
-
его можно было адаптировать под наши задачи без переписывания с нуля.
Альтернативы (например, самостоятельная реализация headless-браузера или сторонние коммерческие сервисы) требовали либо больших затрат на разработку, либо дополнительного бюджета и интеграции.
Итог
В результате мы получили работающее решение, которое сочетает:
-
привычный CSR для пользователей (быстрая разработка, низкая нагрузка на сервер);
-
качественный пререндеринг для поисковых ботов (хорошее SEO);
-
минимальные доработки открытого сервиса вместо тяжелого рефакторинга архитектуры.
Такой гибридный подход позволил нам сохранить микрофронтендовую архитектуру на Module Federation, не жертвовать производительностью для пользователей и при этом обеспечить полную индексацию сайта поисковыми системами.
А вы сталкивались с необходимостью совмещать SSR и CSR в микрофронтендовой архитектуре? Какие решения использовали и с какими трудностями встречались?
ссылка на оригинал статьи https://habr.com/ru/articles/1037280/