Найти в Дзене
Dev Articles

Пришло время для современного CSS покончить с SPA

Нативные CSS-переходы незаметно похоронили главный аргумент в пользу клиентской маршрутизации. Однако люди продолжают создавать ужасные приложения вместо производительных веб-сайтов. «Сделайте так, чтобы это выглядело как приложение». На каком-то из этапов процесса определения требований кто-то произносит эти слова. Директор по маркетингу, руководитель цифровых проектов или бренд-менеджер. И с этой единственной фразой архитектура определена: это будет SPA. Скорее всего, на React. Может быть, на Vue. Почти наверняка будет развёрнуто на Vercel или Netlify, со сборкой headless CMS и GraphQL API для полноты картины. Но решение на самом деле не касалось архитектуры. Оно даже не касалось производительности, масштабируемости или управления контентом. Речь шла о взаимодействии. О том, как сайт будет ощущаться при кликах. Предположение было простым: для плавной навигации нужно создавать приложение. Это предположение теперь устарело. SPA стали стандартом не потому, что они были лучше. Просто как
Оглавление

Нативные CSS-переходы незаметно похоронили главный аргумент в пользу клиентской маршрутизации. Однако люди продолжают создавать ужасные приложения вместо производительных веб-сайтов.

Заблуждение о похожести на приложение

«Сделайте так, чтобы это выглядело как приложение».

На каком-то из этапов процесса определения требований кто-то произносит эти слова. Директор по маркетингу, руководитель цифровых проектов или бренд-менеджер. И с этой единственной фразой архитектура определена: это будет SPA. Скорее всего, на React. Может быть, на Vue. Почти наверняка будет развёрнуто на Vercel или Netlify, со сборкой headless CMS и GraphQL API для полноты картины.

Но решение на самом деле не касалось архитектуры. Оно даже не касалось производительности, масштабируемости или управления контентом. Речь шла о взаимодействии. О том, как сайт будет ощущаться при кликах.

Предположение было простым: для плавной навигации нужно создавать приложение.

Это предположение теперь устарело.

Ложное обещание SPA

SPA стали стандартом не потому, что они были лучше. Просто какое-то время они были единственным способом обеспечить плавность — без белых вспышек между страницами и проблем с позицией прокрутки.

Но вот неприятная правда: большинство SPA на самом деле не обеспечивают того качества, которое обещают.

Обычно вы получаете:

  • Плавный переход между страницами, пока не поймёте, что это просто затухание между двумя состояниями загрузки
  • Сломанный механизм восстановления прокрутки
  • Непоследовательное поведение фокуса
  • Задержка навигации во время регидратации компонентов
  • Смещение макета, появление контента или скелетоны на всю страницу
  • Потеря производительности, совершенно непропорциональная эффекту

Это не теоретические рассуждения. Посмотрите на большинство сайтов, созданных с помощью Next.js, Gatsby или Nuxt. Они загружают килобайты (а часто и мегабайты) JavaScript только для имитации нативной навигации. Логика маршрутизации, код регидратации, индикаторы загрузки — всё это только для того, чтобы воссоздать то, что браузеры уже умели делать изначально.

Вместо плавности вы получаете симуляцию. Вместо быстрого, стабильного и оптимизированного для SEO опыта вы получаете тяжёлую JavaScript-машину, пытающуюся воссоздать нативное поведение, от которого мы отказались.

Мы добавляли тонны JavaScript, чтобы «казаться» быстрыми, делая всё медленнее.

Веб вырос

Пока мы были заняты изобретением навигации на JavaScript, платформа тихо решила эту проблему.

Современные браузеры, особенно основанные на Chromium (Chrome и Edge), теперь поддерживают нативные декларативные переходы между страницами. С помощью View Transitions API вы можете анимировать переходы между двумя документами, включая полную навигацию между страницами, без единой строки JavaScript.

Да, это правда.

То, что мы называем «современным CSS», — это сокращение для View Transitions, Speculation Rules и возврата к нативным функциям браузера, которые всегда были предназначены для обработки навигации, взаимодействия и макета. Эти возможности позволяют создавать богатые, бесшовные интерфейсы без переписывания браузера на JavaScript.

Это означает, что вы можете:

  • Выполнять плавные переходы между страницами
  • Анимировать общие элементы (например, миниатюры → детальная информация о продукте)
  • Сохранять постоянные элементы, такие как заголовки или навигационные панели
  • Делать всё это с реальными URL, реальной загрузкой страниц и без хаков маршрутизации на JavaScript

Давайте разберёмся на примерах.

Базовый переход между страницами

С помощью нескольких строк CSS вы можете создать плавные визуальные переходы между страницами.

На текущей и целевой странице добавьте:

@view-transition {
navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
animation: fade 0.3s ease both;
}

@keyframes fade {
from { opacity: 0; }
to { opacity: 1; }
}

Это всё. Браузер обрабатывает переход самостоятельно – никакого клиентского роутинга, никакой гидрации компонентов, никаких индикаторов загрузки.

Переходы с общими элементами

Хотите анимировать миниатюру изображения в полноразмерное представление продукта на следующей странице?

Нет нужды в JavaScript – достаточно присвоить одному и тому же элементу одинаковое значение свойства view-transition-name на обеих страницах:

На странице списка продуктов:

<a href="/product/red-shoes">
<img src="/images/red-shoes-thumb.jpg" style="view-transition-name: product-image;" />
</a>

На странице информации о продукте:

<img src="/images/red-shoes-large.jpg" style="view-transition-name: product-image;" />

Браузер сопоставляет элементы и анимирует их при навигации. Вы можете анимировать положение, масштаб, прозрачность, макет – всё средствами CSS.

Но что если мне нужны переходы на JavaScript?

Вы также можете вручную запускать переходы внутри страницы:

document.startViewTransition(() => {
document.body.classList.toggle('dark-mode');
});

Идеально подходит для переключения вкладок или смены темы — без использования фреймворка или слоя регидратации.

Правила спекуляций: мгновенная навигация без JavaScript

View Transitions делают переходы плавными. Но как насчёт скорости?

Здесь на помощь приходят правила спекуляций. Они позволяют браузеру предварительно загружать или пререндерить полные страницы на основе поведения пользователя — например, при наведении или касании ссылки — до того, как он нажмёт на неё.

<script type="speculationrules">
{
"prerender": [
{
"where": {
"selector_matches": "a"
}
}
]
}
</script>

Результат? Мгновенная навигация. Без ожидания. Без загрузки. Без спиннеров.

Важное предупреждение

Правила спекуляций — это множитель производительности. На легковесном сайте они делают всё мгновенным. Но если ваши страницы медленные, перегруженные или с большим количеством JavaScript, спекуляции просто перенесут эти затраты вперёд.

Если ваш сайт перегружен, спекуляции всё равно будут работать — и пользователь заплатит за это.

Это означает потраченный впустую CPU, пропускную способность сети и заряд батареи мобильного устройства — часто для страниц, которые пользователь даже не посещает.

Используйте их осторожно. На быстром сайте они — магия. На медленном — ловушка.

Браузеры хотят помочь — если мы позволим

Современные браузеры стали умнее, чем когда-либо. Они постоянно ищут способы улучшить скорость, отзывчивость и эффективность — но только если мы позволим.

Один из ярких примеров — кэш Back/Forward (bfcache), который позволяет сохранять снимки целых страниц и восстанавливать их мгновенно при возврате или переходе вперёд.

Это фактически бесплатная производительность — но только для страниц, которые ведут себя хорошо. Это означает отсутствие проблемного JavaScript, перехваченной навигации, хаоса жизненного цикла. Только чистая декларативная архитектура. Только HTML и CSS.

Неудивительно, что это прекрасно работает с хорошо структурированным многостраничным сайтом. Но для большинства SPA это не подходит. Сами шаблоны проектирования, которые их определяют — перехваченная маршрутизация, рендеринг на стороне клиента, сложное управление состоянием — нарушают предположения, на которых основан bfcache.

Это микрокосм более широкой темы: браузеры эволюционируют, поощряя простоту и устойчивость. Они создают то, что мы должны были использовать всё это время. И SPA всё больше становятся исключением.

SPA против MPA: проверка производительности

Средний маркетинговый сайт на Next.js

  • JS bundle: 1–3 МБ
  • Время до интерактивности: ~3,5–5 секунд (в зависимости от стратегии регидратации)
  • Переходы между маршрутами: симулированные
  • SEO: сложное, хрупкое
  • Поведение прокрутки/якорей: ненадёжное

Современный MPA + View Transitions + Правила спекуляций

  • JS bundle: 0 КБ (только опциональные улучшения)
  • Время до интерактивности: ~1 секунда
  • Переходы между маршрутами: реальные, нативные
  • SEO: простое
  • Прокрутка/фокус/история: браузерные настройки по умолчанию и безупречные

Современный CSS не просто заменяет поведение SPA — он превосходит его.

Не создавайте веб-сайт как приложение

Большинство веб-сайтов не являются приложениями.

Им не нужен общий state. Им не нужна маршрутизация на стороне клиента. Им не нужны интерактивные компоненты на каждом экране. Но в какой-то момент мы перестали проводить это различие.

Теперь мы создаём интернет-магазины, порталы документации, маркетинговые сайты и блоги, используя стеки, предназначенные для интерфейсов с совместной работой в реальном времени. Это безумие.

Главная страница с шестью блоками контента и формой обратной связи не нуждается в регидратации, границах suspense и стратегии рендеринга.

Ей нужна быстрая разметка, чистые URL и, возможно — только возможно — немного интерактивности сверху.

И всё же в каждом проекте:

  • Руководитель говорит: «Сделайте так, чтобы это выглядело как приложение».
  • Команда разработчиков тянется к Next.js или Nuxt.
  • Маршрутизация уходит на клиентскую сторону.
  • Производительность резко падает.
  • Теперь вам нужны edge-функции, стриминг, ISR, стратегии загрузки и план отладки.
  • И каким-то образом… это всё равно ощущается медленнее, чем обычный клик по ссылке и анимация CSS.

Здесь речь вовсе не о ненависти к фреймворкам. Речь идёт об осознанности решений.

Используйте React, если хотите. Используйте Tailwind, Vite или любые другие инструменты. Просто не отправляйте всё это в браузер, если оно действительно не нужно.

Создавайте сайт как обычный сайт. Пользуйтесь HTML. Применяйте стандартную навигацию. Полагайтесь на возможности браузера.

Так быстрее, проще и лучше для всех.

Разрабатывайте для текущего веба

Одностраничные приложения были остроумным решением временной проблемы. Но эта проблема больше не существует.

Сегодня у нас есть:

  • нативные декларативные переходы между настоящими страницами,— мгновенная предрендеренная навигация благодаря правилам спекуляции (Speculation Rules),
  • изящная деградация функциональности,
  • чистая разметка, быстрое открытие страниц и реальные URL'ы,
  • платформа, готовая помогать нам, если мы позволим ей это сделать.

Если вы продолжаете строить свой сайт как одностраничное приложение лишь ради «гладкости», вы решаете проблему, которую браузер давно решил сам, и платите за это сложностью, снижением производительности и проблемами поддержки.

Используйте современные серверные методы рендеринга. Работайте с реальными страницами. Анимируйте с помощью CSS. Предзагружайте осознанно. Отправляйте меньше JavaScript-кода.

Работайте так, словно сейчас 2025 год, а не застряли в демонстрационной версии Gatsby образца 2018-го.

Вы получите быстрые сайты, довольных пользователей и минимум сожалений.

Оригинал статьи читайте по ссылке