Что такое клиентский роутинг в SPA — и что браузер перестаёт делать за тебя

Ты кликаешь по ссылке, адрес в браузере меняется на /about, на экране новая страница. Кажется, что всё как обычно.
А сервер об этом переходе даже не узнал. Никакого запроса не было. Одна и та же страница просто перерисовала себя и поменяла строку в адресной строке.
Так работают одностраничные приложения — SPA. Быстро и плавно. Но есть подвох: раньше при каждом переходе браузер делал за тебя кучу мелкой работы. Теперь её никто не делает, если ты не позаботишься.
Обычный переход и переход в SPA
Обычный сайт. Клик по ссылке → браузер отправляет запрос на сервер → получает новый HTML → выбрасывает старую страницу и рисует новую.
SPA. В MDN определение такое: приложение, которое загружает один HTML-документ, а дальше обновляет его содержимое через JavaScript. Клик по ссылке перехватывается кодом. Код меняет адрес, берёт нужный кусок интерфейса и вставляет его на место старого.
Вот этот перехват и подмена называются клиентским роутингом: решение «что показать по этому адресу» принимает не сервер, а JavaScript в браузере. Если ты работаешь с React, роутинг обычно даёт отдельная библиотека — React Router — или фреймворк вроде Next.js со своим компонентом ссылки.
Как это устроено внутри
Всё держится на History API браузера. Главный метод — history.pushState().
history.pushState({}, "", "/about");
Он добавляет запись в историю и меняет адрес. MDN отдельно подчёркивает: браузер не пытается загрузить этот адрес. Поменялась только строка. Показать нужный экран — уже работа твоего кода.
Две детали, которые удивляют почти всех:
- Второй аргумент ничего не делает. Когда-то он задумывался как заголовок страницы. MDN сейчас называет его
unused: параметр оставлен по историческим причинам, передавать можно пустую строку. - Кнопка «Назад» — отдельный сигнал. Когда человек жмёт «Назад» или «Вперёд», браузер присылает событие
popstate. А сам вызовpushStateэто событие не запускает. Роутер слушаетpopstateи перерисовывает экран под старый адрес.
Четыре вещи, которые браузер больше не делает за тебя
Вот ради чего стоило дочитать. При обычном переходе всё это происходило само. В SPA за каждое отвечает роутер — и иногда не отвечает никто.
- Прокрутка наверх. Обычная новая страница открывается с начала. В SPA ты дочитал статью до конца, кликнул «Следующая» — и новая открылась сразу внизу. Хорошие роутеры это чинят: у React Router есть компонент
ScrollRestoration, у Next.js ссылки по умолчанию прокручивают наверх. - Заголовок вкладки.
pushStateего не меняет — тот самый бесполезный второй аргумент. Если код не обновитdocument.title, во вкладке и в истории браузера у всех страниц будет одно и то же имя. - Объявление для скринридера. При обычной загрузке скринридер зачитывает заголовок новой страницы, и незрячий человек понимает: переход случился. В SPA тишина. Next.js встроил для этого «объявлятель маршрутов»: он ищет название в
document.title, потом вh1, потом берёт путь из адреса. В самописном роутинге этого нет, пока ты не добавишь. - Сервер про адрес ничего не знает. Внутри приложения
/aboutработает. А если открыть этот адрес напрямую или нажать «Обновить», запрос уйдёт на сервер — а у него файла/aboutнет. Отсюда классический баг, который мы разобрали отдельно: почему страница выдаёт 404 после обновления.
Как проверить своё приложение за пять минут
ИИ легко генерирует SPA, и почти никогда не проверяет эти четыре пункта сам. Пройдись руками:
- Прокрути длинную страницу вниз, перейди по ссылке. Новая открылась сверху?
- Перейди на три разные страницы и посмотри на название вкладки. Оно меняется?
- Нажми «Назад» два раза. Приложение возвращает прошлые экраны или выкидывает с сайта?
- Скопируй адрес внутренней страницы, открой его в новой вкладке. Открылось или 404?
Если хоть что-то сломано — это не повод бросать SPA. Это список задач для роутера. А нужен ли тебе SPA вообще, помогает решить разбор React или чистый HTML. Кстати, в адрес можно класть не только страницу, но и состояние экрана — фильтры, сортировку, вкладку. Как это делается, показали в инструкции как сохранить фильтры в URL.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.
Клиентский роутинг вредит SEO?
MDN прямо называет SEO одним из компромиссов SPA: поисковику и превью-ботам нужно выполнить JavaScript, чтобы увидеть содержимое. Для кабинета за логином это неважно, для блога или магазина лучше рендер на сервере.
Чем он отличается от адресов с решёткой (#/about)?
Хеш-роутинг кладёт путь после #, а эта часть адреса на сервер не отправляется. Поэтому обновление страницы не ломается — зато адреса выглядят некрасиво. У React Router для этого есть отдельный режим.
Мне нужно писать роутинг самому?
Нет, бери готовый роутер — React Router, роутинг Next.js или то, что встроено в твой фреймворк. Твоя задача — проверить четыре пункта выше, а не изобретать pushState заново.





