Wybór między SSR a SPA wpływa na wydajność, SEO i doświadczenie użytkownika. Poznaj kluczowe różnice, zalety, wady i nowoczesne podejścia hybrydowe w budowie aplikacji webowych.
Dwa modele renderowania — i kilka pomiędzy
Wybór między SSR (Server-Side Rendering) a SPA (Single Page Application) to jedna z pierwszych decyzji architektonicznych przy budowie aplikacji webowej. Ma bezpośredni wpływ na SEO, czas ładowania, interaktywność i koszty utrzymania. W praktyce rzadko spotykamy „czysty" SSR lub „czyste" SPA — większość projektów, które realizujemy, to rozwiązania hybrydowe. Ten artykuł porównuje oba podejścia z perspektywy inżynierskiej: co zyskujesz, co tracisz i kiedy warto rozważyć alternatywy.
SSR — rendering po stronie serwera
W modelu SSR serwer generuje kompletny HTML dla każdego żądania. Przeglądarka dostaje gotową stronę i wyświetla ją natychmiast — bez czekania na załadowanie i uruchomienie JavaScriptu. To podejście dominowało w sieci przez dekady (PHP + szablony, Django + Jinja2, Ruby on Rails + ERB) i nadal jest standardem w witrynach contentowych, e-commerce i portalach korporacyjnych.
Zalety SSR
- SEO — boty wyszukiwarek dostają pełny HTML bez konieczności wykonywania JS. Google deklaruje, że renderuje JavaScript, ale w praktyce indeksowanie SSR jest szybsze i bardziej przewidywalne.
- Szybsze FCP i LCP — przeglądarka wyświetla treść zanim załaduje się cały bundle JS. Przy dobrze skonfigurowanym serwerze TTFB wynosi 50–200 ms.
- Mniej JS na kliencie — niższe TBT (Total Blocking Time), lepsze wyniki INP (Interaction to Next Paint), co od marca 2024 jest Core Web Vital.
Wady SSR
- Każde żądanie generuje HTML na serwerze — przy dużym ruchu potrzebujesz cache'owania (Varnish, CDN, cache w aplikacji) lub większej infrastruktury.
- Nawigacja między stronami powoduje pełne przeładowanie — użytkownik widzi miganie strony, chyba że zastosujesz techniki jak Turbo (Hotwire), HTMX lub partial hydration.
- Dynamiczne komponenty (modale, filtry, drag & drop) wymagają dociągnięcia JS, co komplikuje architekturę.
Typowe technologie
Laravel + Blade, Symfony + Twig, Django + Jinja2, Ruby on Rails + ERB, a w ekosystemie JS: Next.js (React) i Nuxt (Vue) w trybie SSR.
SPA — Single Page Application
SPA ładuje logikę frontendową jednorazowo (bundle JS), a potem komunikuje się z backendem przez API (REST lub GraphQL). Widoki aktualizują się dynamicznie bez przeładowania strony. Rezultat: płynna nawigacja, poczucie natywnej aplikacji, separacja frontendu od backendu.
Zalety SPA
- Interaktywność — nawigacja bez przeładowania, natychmiastowa reakcja na akcje użytkownika. Sprawdza się w dashboardach, paneli admina, aplikacji z dużą ilością interakcji (Trello, Figma, Google Docs).
- Separacja frontend/backend — frontend konsumuje API, backend jest niezależny od warstwy prezentacji. Ułatwia pracę rozproszonych zespołów i pozwala na wieloplatformowość (ta sama API dla web, mobile, integracji).
- Bogaty ekosystem — React, Vue, Angular, Svelte oferują dojrzałe narzędzia: routing, state management, dev tools.
Wady SPA
- SEO — bez prerenderingu lub SSR boty widzą pustą stronę. Googlebot renderuje JS, ale z opóźnieniem (kolejka renderowania). Bing, DuckDuckGo i boty mediów społecznościowych radzą sobie gorzej.
- Duży bundle JS — React + React DOM to ok. 140 kB (gzip). Dodaj routing, state management i UI library — łatwo przekroczyć 500 kB. Na wolnym połączeniu (3G) ładowanie takiego bundle'a trwa 5–10 sekund.
- INP i TBT — duży JS blokuje main thread. Od marca 2024 INP (Interaction to Next Paint) zastąpił FID w Core Web Vitals. SPA z ciężkim bundle'm mają z tym problem — szczególnie na urządzeniach mobilnych.
Rozwiązania hybrydowe — gdzie zmierza branża
Podział na SSR i SPA jest uproszczeniem. Współczesne frameworki łączą oba podejścia:
- Next.js (React) — obsługuje SSR, SSG (Static Site Generation), ISR (Incremental Static Regeneration) i React Server Components. Pozwala renderować część strony na serwerze, a interaktywne komponenty hydrować po stronie klienta.
- Nuxt (Vue) — analogicznie do Next.js, z SSR, SSG i hybrydowym renderowaniem. Dobra dokumentacja w języku polskim.
- Astro — podejście „server-first" i „islands architecture". Domyślnie wysyła zero JS do klienta. Interaktywne wyspy (np. formularz, karuzela) hydrują się niezależnie. Strona contentowa w Astro waży często poniżej 50 kB.
- SvelteKit — kompiluje komponenty do natywnego JS (bez virtual DOM). Bundle'e są mniejsze niż w React/Vue. Obsługuje SSR, SSG i SPA w jednym projekcie.
- HTMX / Hotwire (Turbo + Stimulus) — zamiast pisać SPA, dodajesz interaktywność do klasycznego SSR przez atrybuty HTML. Serwer zwraca fragmenty HTML, klient podmienia elementy DOM. Zero konfiguracji bundlera, minimalne JS.
Streaming SSR i partial hydration
React 18 wprowadził streaming SSR — serwer zaczyna wysyłać HTML zanim zakończy renderowanie całej strony. Przeglądarka wyświetla zawartość stopniowo, co poprawia TTFB i FCP. W połączeniu z React Server Components (RSC) pozwala to renderować części strony wyłącznie na serwerze, bez wysyłania ich kodu JS do klienta.
Partial hydration (dostępna w Astro, Qwik i eksperymentalnie w Next.js) idzie krok dalej: hydruje tylko te komponenty, które tego wymagają. Reszta strony pozostaje statycznym HTML. To rozwiązanie problemu „doliny niesamowitości" — gdy strona wygląda na załadowaną (HTML widoczny), ale nie reaguje na kliknięcia (JS jeszcze się nie załadował).
Jak wybrać podejście do swojego projektu
- Witryna contentowa, blog, e-commerce z katalogiem — SSR lub SSG (Next.js, Nuxt, Astro). SEO jest priorytetem, interaktywność ograniczona do koszyka i filtrów.
- Dashboard, panel admina, aplikacja wewnętrzna — SPA (React, Vue, Angular). SEO nie ma znaczenia, liczy się płynna interaktywność.
- Aplikacja publiczna z dużą interaktywnością i wymaganiami SEO — podejście hybrydowe (Next.js z RSC, Nuxt, SvelteKit). Kosztuje więcej w implementacji, ale daje najlepsze wyniki.
- Jeśli masz istniejący system SSR (PHP, Django, Rails) i chcesz dodać interaktywne elementy — rozważ HTMX lub Livewire zamiast przepisywania na SPA. Przy modernizacji systemów często stosujemy to podejście.
- Zmierz INP i LCP na realnych urządzeniach (Chrome UX Report) przed podjęciem decyzji o migracji. Liczby z PageSpeed nie zawsze odzwierciedlają doświadczenie użytkownika — pisaliśmy o tym osobno.
Źródła
- Google Search Central — JavaScript SEO basics — jak Googlebot radzi sobie z JS i co to oznacza dla SPA.
- web.dev — Core Web Vitals — aktualne definicje LCP, INP i CLS (od marca 2024 INP zamiast FID).
- Astro — Why Astro? — opis podejścia server-first i islands architecture.
- HTMX — biblioteka dodająca AJAX, WebSocket i SSE do HTML przez atrybuty (bez pisania JS).