SPA vs SSR vs SSG vs ISR vs RSC streaming — где и когда мы превращаем данные в HTML. Build-time → CDN edge → origin Node → client browser. Trade-offs: TTFB, SEO, dynamic data freshness, infra cost. 5 сценариев: SPA blank-then-fill, SSR per-request render + hydrate, SSG/ISR pre-built на CDN, RSC streaming через Edge с Suspense, anti-pattern (SPA для marketing landing). 2 ADR: дефолтный выбор в 2026 (Next.js App Router + RSC) и правило близости рендеринга к user.
Выбор SPA, SSR, SSG, ISR или RSC - это не вопрос вкуса во фреймворках. Это решение о том, где и когда HTML появляется из данных: на build-сервере, на CDN edge, на origin Node-сервере или уже в браузере пользователя. От этого прямо зависят TTFB, LCP, SEO, стоимость compute, размер JavaScript-бандла, сложность кэширования и количество багов гидратации.
Типовая ошибка команды: взять React SPA для лендинга, потому что команда умеет React. В итоге CDN быстро отдает почти пустой index.html, но пользователь и поисковик ждут загрузки, парсинга и выполнения большого JS-бандла. Обратная ошибка: сделать SSR для блога или документации, где контент меняется раз в неделю. Тогда каждый запрос зря занимает серверный CPU, хотя страница могла бы лежать статикой на CDN.
Эта тема связывает frontend-архитектуру с системным дизайном. Вы больше не спрашиваете "Next или Vite?". Вы спрашиваете: насколько свежими должны быть данные, нужен ли SEO, где находится база, какой p75 LCP нужен бизнесу, сколько интерактивности есть above the fold и кто платит за render.
Рендеринг идет по шкале близости к build-time и пользователю:
ADR-правило из диаграммы: рендерить как можно ближе к build-time, пока требования к свежести и персонализации не заставят двигаться вправо к edge, origin или client.
Диаграмма раскладывает одну страницу по четырем зонам: Build time, Edge / CDN, Origin и Browser. ssg-builder собирает HTML и публикует его в cdn. cdn отдает готовые страницы и статические чанки. edge-fn показывает RSC/streaming путь, когда shell можно отдать быстро, а медленные данные дослать позже через Suspense. ssr-server, api и db показывают классический origin SSR: сервер ждет данные, рендерит React в HTML и только потом отвечает. В браузере есть shell и hydrated, чтобы видно было различие между первым HTML и интерактивным приложением после загрузки JS.
Важно, что ребра не обозначают "ответные" соединения. Например, API не обязан иметь отдельную стрелку назад к браузеру: FlowBuilder анимирует ответ по существующему соединению в обратном направлении. Так диаграмма учит правильной модели: физические зависимости одни, сценарии движения данных разные.
spa показывает classic CRA/Vite путь. CDN быстро отдает маленький index.html, затем браузер загружает bundle.js, монтирует React, делает fetch в API, ждет БД и только потом рисует полезный контент. Урок: быстрый TTFB у SPA не равен быстрому UX. Для Gmail, Figma canvas, Linear app и сложных кабинетов это нормально: SEO не нужен, интерактивность важнее первого HTML. Для маркетинга это анти-паттерн.
ssr показывает per-request render. Origin Node получает запрос, вызывает API/DB, собирает HTML и отдает страницу с данными. Пользователь быстро видит контент, поисковик получает нормальный HTML, но сервер теперь участвует в каждом просмотре. Урок: SSR покупает SEO и first paint ценой origin latency, контейнеров, cold starts и hydration mismatch.
ssg-isr показывает build-time HTML и CDN delivery. Для SSG compute платится один раз на CI, а каждый пользователь получает готовую страницу. ISR добавляет revalidate: первый запрос после TTL может получить stale-версию, а следующий уже свежую. Урок: если freshness допускает минуты или часы, SSG/ISR почти всегда лучше SSR.
rsc-streaming показывает React Server Components и Suspense. Server-only код, например markdown parser или ORM adapter, не попадает в браузерный JS. Shell можно отдать раньше, а slow boundary доставить позже. Урок: RSC - не просто "SSR 2.0", а способ сократить client bundle и разделить интерактивные client components от server-rendered частей.
anti-pattern сценарий фиксирует частую ошибку: SPA для публичного лендинга или SSR/edge там, где статическая генерация закрывает задачу. Урок: выбирать надо per-surface, а не одним решением на весь продукт.
ADR-001 в диаграмме предлагает дефолт на 2026 год: Next.js App Router + RSC + selective SSG для нового web app, где есть и публичные страницы, и динамические зоны. Причина не в моде на Next, а в per-route выборе стратегии: force-static для лендинга, revalidate для product pages, server components для тяжелого server-only кода, server actions для типовых мутаций.
Но ADR не говорит "Next всегда". Если приложение - чистый after-login dashboard без SEO, Vite + React Router проще: нет сервера рендеринга, меньше operational surface, дешевле хостинг. Если это сайт контента почти без JS, Astro часто лучше: islands architecture и zero JS by default дают меньше клиентского кода. Если core уже Rails/Django, иногда выгоднее Turbo/Hotwire с React-островами, чем переносить все в SSR-фреймворк.
ADR-002 формализует шкалу build -> edge -> origin -> client. Чем левее, тем дешевле и быстрее первый байт; чем правее, тем больше свежести, персонализации и интерактивности. Edge не магия: edge-функция, которая ходит в Postgres в другом регионе, превращает proximity в лишний round-trip. SSR рядом с БД может быть быстрее, чем edge рядом с пользователем, если данные все равно живут в одном регионе.
Vercel docs и Next.js docs используют RSC, SSG и edge-подходы там, где важен быстрый контент и хороший DX. Notion разделяет поверхности: marketing ближе к SSG, редактор - сложное SPA. Linear делает публичный сайт статическим, а продуктовый интерфейс - client-heavy app. Stripe.com использует быстрые статические/серверные страницы для маркетинга, а Dashboard живет как after-login приложение. Shopify Hydrogen и Remix показывают SSR/BFF-подход для storefront, где SEO и свежесть товара важны одновременно. GitHub исторически ближе к server-rendered HTML с точечными интерактивными островами, что напоминает: React SPA - не единственный способ строить современный веб.
revalidate=1: фактически SSR под видом статической страницы, часто без ясной модели кэша.Не используйте SPA для страниц, где SEO, preview cards, быстрый LCP и доступность без JS критичны: лендинги, документация, блог, каталог. Не используйте SSR для полностью статичного контента с редкими обновлениями. Не используйте SSG для персонализированного HTML, финансовых данных, корзины и страниц, где stale-данные опасны. Не используйте Edge для тяжелого Node.js runtime, долгих DB-соединений, CPU-heavy render и регионально удаленных данных. Не используйте RSC как оправдание переносить всю логику в серверные компоненты: интерактивный canvas, realtime editor и complex form wizard все равно требуют сильной client-side модели.
Внешние ориентиры: Next.js Rendering docs, Jason Miller "Rendering on the Web", Patterns.dev Rendering Patterns, Dan Abramov "The Two Reacts", Astro Islands Architecture и Remix materials про data loading.