В чём основная проблема клиентского React-приложения
Классическое приложение на React отдаёт браузеру пустой HTML-документ и набор скриптов. Все «страницы» строятся уже на стороне пользователя. Как мы разбирали в статье про одностраничные приложения, робот может выполнить скрипты, но делает это с задержкой и не всегда надёжно.
Настоящие ссылки вместо обработчиков кликов
Робот переходит только по элементам со ссылкой в атрибуте href. Навигация, построенная на обработчиках событий, для него невидима.
// Плохо: робот не найдёт ссылку
<div onClick={() => navigate('/catalog')}>Каталог</div>
// Хорошо: настоящая ссылка
<Link to="/catalog">Каталог</Link>
Компонент Link в итоге формирует обычный элемент со ссылкой, а перехват клика для быстрой навигации остаётся удобной надстройкой для пользователя.
Выбор между BrowserRouter и HashRouter
- BrowserRouter создаёт обычные адреса без решётки и подходит для индексации;
- HashRouter помещает маршрут после решётки — для публичных страниц его использовать не стоит;
- BrowserRouter требует настройки сервера на отдачу приложения для внутренних путей.
Серверный рендеринг для публичных страниц
Если сайт должен занимать места в поиске, надёжнее всего отдавать роботу готовый HTML. Для этого используют фреймворки с серверным рендерингом либо предварительную генерацию страниц. Так вы получаете преимущества React и не зависите от того, как робот исполнит ваши скрипты.
Практика: для закрытых разделов, например личного кабинета, серверный рендеринг не нужен — такие страницы всё равно закрывают от индексации.
Страница «не найдено» и корректный статус
Маршрут-заглушка в React Router отрисует сообщение, но код ответа сервера останется 200. Чтобы отдать 404, статус нужно задавать на стороне сервера при рендеринге. Без этого несуществующие адреса будут выглядеть для робота как полноценные страницы.
Предварительный рендеринг для небольших сайтов
Если полноценный серверный рендеринг кажется избыточным, для небольшого числа страниц можно применить предварительную генерацию: во время сборки специальный инструмент обходит маршруты и сохраняет готовый HTML каждого из них. Робот получает содержимое сразу, а пользователь — быстрый интерактивный интерфейс.
Заголовки и мета-теги для каждого маршрута
В клиентском приложении заголовок страницы и описание нужно менять при каждом переходе. Для этого подключают специальную библиотеку управления содержимым раздела head. Убедитесь, что значения формируются из данных конкретной страницы и присутствуют в HTML, который получает робот, а не появляются лишь после выполнения скриптов.
Проверка: просмотрите исходный код страницы, а не то, что показывают инструменты разработчика после загрузки. Именно исходный код видит робот при первом обращении.
Частые вопросы
Почему робот не видит навигацию, сделанную на обработчиках кликов?
Робот переходит только по элементам со ссылкой в атрибуте href, а обработчики событий он не выполняет как пользователь.
Можно ли использовать HashRouter на публичном сайте?
Не рекомендуется: часть адреса после решётки поисковая система различает плохо, поэтому для индексируемых страниц выбирают BrowserRouter.
Как вернуть код 404 в приложении на React?
Статус нужно задавать на стороне сервера при отрисовке страницы, поскольку клиентская заглушка сама по себе оставляет код 200.
Готовый адрес можно собрать прямо сейчас: откройте генератор ЧПУ — он транслитерирует фразу по таблице Яндекса, уберёт служебные слова и покажет длину адреса.