Пользователь меняет фильтр, открывает заказ и возвращается к списку. В хорошем рабочем интерфейсе он не теряет выбранные параметры и не ждёт полной перезагрузки при каждом действии. SPA позволяет построить такое взаимодействие, но удобство зависит от маршрутов, данных и обработки ошибок.
В Гуси-Лебеди мы предлагаем выбирать SPA по задачам продукта. Разберём, как работает одностраничное приложение, чем оно отличается от MPA и PWA, что проверять для SEO и как выпускать изменения. Пример в статье условный: публичный каталог с закрытым кабинетом заказчика.
Что такое SPA и чем оно отличается от MPA и PWA

SPA, Single Page Application, представляет собой веб-приложение, в котором содержимое текущего документа обновляется JavaScript при переходах и действиях. Не требуется каждый раз загружать новый документ целиком. Такое определение приведено в справочнике MDN.
«Одностраничное» не означает один адрес или один экран. У приложения могут быть каталог, карточки и кабинет с отдельными URL. Обычный лендинг с длинной страницей не становится SPA только из-за малого числа разделов.
| Понятие | Что описывает | Что нужно проверить отдельно |
|---|---|---|
| SPA | Обновление интерфейса внутри текущего документа | Первую загрузку, маршруты и состояние |
| MPA | Переходы между отдельными документами | Скорость и удобство каждого сценария |
| PWA | Возможности веб-приложения на устройстве | Установку, кеширование и работу без сети |
| CSR | Подготовку интерфейса в браузере | Загрузку кода и данных |
| SSR или SSG | Подготовку HTML на сервере или заранее | Актуальность, гидратацию и взаимодействие |
Эти признаки могут сочетаться. Серверный первый ответ совместим с клиентскими переходами после загрузки. PWA-возможности тоже не требуют единственной модели маршрутизации. Поэтому вопрос «SPA или PWA» следует уточнить: какие именно свойства нужны продукту?
Когда SPA подходит проекту

Рассматривайте SPA для длительной работы в одном контексте: управление заказами, редактирование, выбор параметров и переключение связанных панелей. Здесь полезно сохранять состояние между действиями. Но частичные обновления должны оставаться понятными: пользователь видит, что изменилось и какой результат подтверждён.
Для небольшого сайта услуг сложный клиентский слой может не дать достаточной пользы. Сравните необходимую интерактивность, публичный контент, первые переходы из поиска и стоимость сопровождения. Если задача решается обычной страницей и формой, архитектуру не нужно усложнять только ради знакомого фреймворка.
Публичный каталог и закрытый кабинет можно проектировать с разными требованиями. Каталогу нужны доступные страницы и содержимое, кабинету стабильная работа с персональными данными. Выбор SSR, CSR или предварительной генерации обсуждают на уровне маршрутов.
При разработке приложения на React или создании интерфейса на Vue.js сначала согласуйте сценарии, границы состояния и источники данных. Библиотека помогает реализовать интерфейс, но не определяет правила обработки заказа за команду.
Как спроектировать маршруты и прямое открытие страниц

Адрес заказа должен работать не только после нажатия в меню, но и при прямом открытии, обновлении страницы и переходе из закладки. Для каждого маршрута укажите начальное состояние, параметры, проверку доступа и поведение при отсутствии объекта.
Клиентская навигация может использовать History API для управления историей. Это не отменяет настройки серверной обработки адресов. Нельзя без разбора отдавать оболочку приложения для любого URL, включая отсутствующий API или файл.
Продумайте, что хранится в адресе, а что только в текущем интерфейсе. Фильтры и сортировка могут потребовать воспроизводимой ссылки, черновик формы другого срока жизни. Не помещайте секреты и персональные данные в URL. Правила сохранения параметров нужно согласовать вместе с продуктом.
Проверьте кнопку «Назад», открытие в новой вкладке и возвращение к списку. После смены маршрута заголовок и фокус должны помогать ориентироваться. Изменение центрального блока без понятной обратной связи может быть неудобным для пользователя клавиатуры и вспомогательных технологий.
Как избежать устаревших данных и ошибок при быстрых действиях

Разделите состояние адреса, временный ввод и данные сервера. Фильтр списка не должен случайно сбрасывать черновик заказа. После выхода из аккаунта персональные данные не должны оставаться доступными следующей сессии через клиентский кеш.
Условный пример: пользователь вводит короткий поисковый запрос, затем уточняет его. Ответ первого запроса приходит позже второго. Если принимать ответы без проверки актуальности, старые результаты заменят новые. Интерфейс покажет один текст в поле и другой набор данных.
Для такого сценария нужна проверка, что ответ относится к текущему запросу и экрану. Отмена устаревшего запроса может помочь с нагрузкой, но не заменяет проверку состояния. Ограничение частоты отправки при вводе также не гарантирует правильный порядок ответов.
Различайте загрузку, пустой ответ, ошибку доступа и недоступность сервиса. У нового пользователя ещё нет заказов, а у существующего список может не загрузиться. Эти состояния требуют разных сообщений и действий. При исправимой ошибке формы сохраняйте введённые данные.
Для изменяющей операции, например создания заказа, потеря ответа не доказывает отсутствие результата на сервере. Нужны идентификатор действия и проверка состояния перед повтором. Эти требования следует включить в контракт API-интеграции.
Что учитывать для SEO публичных маршрутов SPA

Для важных переходов используйте доступные ссылки с адресом в href. У каждой публичной страницы должны быть нужное содержимое, заголовок и согласованные метаданные. Проверьте прямую загрузку и состояние после выполнения JavaScript, а не только переход внутри уже открытого приложения.
Google описывает этапы обхода и рендеринга, корректные ссылки и HTTP-статусы в документации JavaScript SEO. Возможность обработки JavaScript не гарантирует индексацию любой реализации. Особенно внимательно проверьте пустые ответы, ошибки маршрутов и сигналы, меняющиеся после загрузки.
Для отсутствующей страницы нужен корректный результат обработки, а не одинаковая успешная оболочка на каждом выдуманном адресе. Title и canonical должны соответствовать маршруту. Служебные фильтры и варианты адресов согласуйте так, чтобы не создавать неконтролируемые дубли.
SSR и предварительная генерация могут помочь подготовить публичное содержимое, но не заменяют доступные ссылки, правильные ответы и проверку метаданных. Закрытый кабинет защищают контролем доступа. Запрет обхода поисковым роботом не является защитой персональных данных.
Как проверить скорость и выпускать обновления

Измеряйте первое открытие и внутренние переходы отдельно. Условия прогретого кеша и уже загруженного приложения отличаются от первого визита. Проверьте слабое устройство, задержку сети и ошибки данных. Изображение готового интерфейса ещё не подтверждает, что кнопки работают.
| Сценарий проверки | Что подтвердить |
|---|---|
| Первый вход | Есть нужное содержание и доступное действие |
| Прямой адрес | Маршрут открывается после обновления |
| Быстрые переходы | Старый ответ не заменяет текущие данные |
| Ошибка API | Понятное состояние и безопасный следующий шаг |
| Выход из аккаунта | Закрытые данные очищены и доступ отозван |
| Новая версия | Старые сессии и нужные ресурсы обработаны по плану |
При оценке Core Web Vitals учитывайте метод измерения. Один лабораторный запуск не описывает всех посетителей и переходы приложения. Для внутренних сценариев дополнительно фиксируйте готовность содержимого и успешное действие пользователя.
Перед выпуском проверьте совместимость клиента и API, доступность файлов для открытых сессий и процедуру возврата. Если обновление требует перезагрузки, объясните её и предусмотрите сохранение допустимого черновика. Не заставляйте пользователя терять введённые данные без предупреждения.
Мы предлагаем принимать SPA по сценариям, зафиксированным на этапе прототипирования. Рабочие маршруты, понятные состояния и проверенный выпуск дают больше оснований для выбора архитектуры, чем обещание, что одностраничное приложение всегда быстрее.
