Statyczne strony są szybkie, tanie w utrzymaniu i świetnie nadają się do cache'owania na CDN. Problem zaczyna się dopiero wtedy, gdy w tej statycznej stronie pojawia się jeden mały element, który musi być świeży dla każdego użytkownika: avatar po zalogowaniu, licznik komentarzy, cena przeliczona po aktualnym kursie albo rekomendacje dopasowane do bieżącej sesji.
Klasyczna reakcja brzmi: „skoro jest dynamika, cała strona musi przejść na SSR”. Tylko że wtedy tracisz największą zaletę Astro: gotowy HTML, który można szybko podać z CDN bez uruchamiania serwera dla każdego wejścia. Server Islands w Astro to komponenty renderowane na serwerze w osobnym żądaniu, po wysłaniu głównego HTML-a strony. rozwiązują ten problem bardziej precyzyjnie. Statyczna część strony zostaje statyczna, a tylko wybrany fragment jest renderowany na żądanie.
Czym są Server Islands
Server Island to komponent, który renderuje się na serwerze, ale osobno od głównej strony. Pierwsza odpowiedź HTTP zawiera statyczną stronę z miejscem zastępczym tam, gdzie później pojawi się wyspa. Dopiero kolejne żądanie, wykonane automatycznie przez mały skrypt dodany przez Astro, pobiera wyrenderowaną zawartość wyspy i podmienia placeholder.
Kluczowa różnica względem dyrektyw client:* jest prosta: Server Island nie renderuje się w przeglądarce. Jej treść powstaje na serwerze, więc może sięgać do bazy danych, używać sekretów, cookies i sesji — dokładnie tak jak zwykły SSR. Różnica polega na tym, że nie blokuje głównej odpowiedzi strony.
Kiedy Server Islands wygrywają
Scenariusz 1: strona produktu e-commerce. Większość treści (opis, galeria, specyfikacja, recenzje) jest statyczna i zmienia się rzadko. Jeden fragment dynamiczny — stan magazynu — musi być aktualny. Bez Server Islands albo cała strona jest SSR (wolno, drogo), albo pokazujesz nieaktualny stan.
Scenariusz 2: blog z avatarem zalogowanego użytkownika. Sam artykuł jest statyczny i trzymany w cache. Avatar i menu użytkownika w nagłówku muszą być dynamiczne.
Scenariusz 3: personalizowane rekomendacje pod artykułem. Treść artykułu się nie zmienia. Sekcja „Polecamy dla Ciebie” może jednak wyglądać inaczej dla każdego użytkownika.
W każdym z tych przypadków Server Islands pozwalają zachować Cache-Control: public, max-age=3600 dla głównej strony, a dynamiczne fragmenty obsłużyć osobnym żądaniem.
Podstawowa konfiguracja
Server Islands wymagają adaptera SSR. W Astro 6 możesz użyć dowolnego — Node, Vercel, Netlify, Cloudflare:
Potem oznaczasz komponent dyrektywą server:defer:
A sam komponent wyspy:
Wewnątrz wyspy masz pełen dostęp do Astro.cookies, Astro.request, baz danych i sekretów środowiskowych — wszystkiego, co daje SSR. Całość wykonuje się jednak w osobnym żądaniu, więc główna strona nadal może być agresywnie cache'owana.
Fallback, czyli stan zastępczy
slot="fallback" nie jest kosmetyką. To element, który realnie wpływa na UX i Core Web Vitals. Bez fallbacku użytkownik widzi przez chwilę pustą przestrzeń, a potem zawartość wyspy pojawia się nagle. Efekt to skok layoutu, czyli CLS, którego Google nie lubi.
Zasada kciuka: fallback powinien mieć ten sam rozmiar co finalna zawartość wyspy:
Dla ekranów szkieletowych:
CSS do skeletonu (Tailwind):
Użytkownik widzi, że coś się ładuje, layout zostaje stabilny, a CLS nie wymyka się spod kontroli.
Jak działa to technicznie
Kiedy Astro renderuje stronę z Server Islands:
- Każda wyspa
server:deferjest wydzielona do osobnej, wewnętrznej ścieżki/_server-islands/{name}. - W głównym HTML-u jest wstawiony placeholder i mały skrypt, który po załadowaniu strony robi
fetch()do endpointu wyspy. - Odpowiedź z wyspy, czyli jej HTML, jest podmieniana w miejscu placeholdera.
Dla przeglądarki wygląda to jak:
Propsy przekazywane do wyspy są szyfrowane kluczem generowanym podczas buildu i przekazywane w URL-u jako parametr. Dzięki temu:
- Możesz bezpiecznie przekazywać dane użytkownika bez ryzyka prostej podmiany wartości.
- Astro wspiera cache'owanie przez
Cache-Control— jeśli propsy są te same, Cloudflare czy CDN mogą zcache'ować odpowiedź wyspy.
Ograniczenie: URL nie może przekroczyć 2048 bajtów. Jeśli propsy są zbyt duże, Astro przełącza się na POST, którego nie da się tak łatwo cache'ować. Wniosek praktyczny: przekazuj do wyspy tylko minimalne ID, a resztę danych pobieraj wewnątrz.
Server Islands a Partial Prerendering w Next.js
Wygląda podobnie? Next.js 15+ ma Partial Prerendering (PPR) + streaming z Suspense, co na pierwszy rzut oka rozwiązuje ten sam problem. Ale mechanika jest inna:
| Aspekt | Astro Server Islands | Next.js PPR |
|---|---|---|
| Model mentalny | Wyspa jako osobny endpoint | Granica Suspense w obrębie jednej strony |
| Dostawa | Drugie żądanie HTTP | Streaming w pierwszym żądaniu |
| Runtime klienta | Mały skrypt do pobrania i podmiany HTML-a | Runtime Reacta + logika streamingu |
| Cache'owanie | Osobne reguły Cache-Control dla wyspy | Cache całości lub nic (granularność ograniczona) |
| Kiedy wygrywa | Rzadko zmieniane strony + drobne dynamiczne dane | Aplikacje z dużą ilością SSR + wyspowe dane |
PPR jest mocniej zintegrowany z ekosystemem Reacta i zwykle lepiej pasuje do aplikacji. Server Islands są prostsze koncepcyjnie i bardzo dobrze pasują do stron zorientowanych na treść. Nie ma tu jednego zwycięzcy — są dwa różne sposoby rozwiązania tego samego problemu. Ogólne porównanie obu frameworków opisuję w osobnym artykule.
Praktyczny przykład — licznik komentarzy
Weźmy prosty przykład: blog z ponad setką artykułów. Każdy artykuł jest generowany statycznie i trzymany w cache CDN przez godzinę. Do tego chcemy pokazać aktualny licznik komentarzy.
Bez Server Islands wrzucasz fetch() do API komentarzy bezpośrednio w szablonie. Strona staje się SSR, trudniej ją cache'ować, bo liczba komentarzy stale się zmienia, a odpowiedź robi się wolniejsza.
Z Server Islands:
Efekt: artykuł nadal może leżeć w cache CDN przez godzinę, a licznik komentarzy odświeża się przy każdym wejściu albo korzysta z krótszego cache ustawionego bezpośrednio dla wyspy.
Ograniczenia i pułapki
1. Propsy muszą być serializowalne. Nie przekażesz funkcji, klas ani komponentów do Server Island. Tylko prymitywy, tablice, obiekty JSON, daty.
2. Astro.url wewnątrz wyspy wskazuje ścieżkę wyspy, nie strony. Wewnątrz komponentu Astro.url zwróci /_server-islands/CommentsCount?..., nie /blog/my-post. Jeśli potrzebujesz URL strony, czytaj nagłówek Referer:
3. Wyspa nie widzi zmiennych kontekstu z głównego renderu. Każda wyspa renderuje się w izolowanym żądaniu. Jeśli w głównej stronie ustawisz zmienną, wyspa jej nie zobaczy — musisz przekazać przez propsy.
4. Cache i prywatne dane. Jeśli wyspa zwraca dane zależne od użytkownika, takie jak avatar albo personalizacja, musisz ustawić Cache-Control: private lub no-store, żeby CDN nie podał cudzych danych kolejnej osobie.
Cache, prywatność i stan zastępczy
Server Island jest świetnym narzędziem tylko wtedy, gdy świadomie rozdzielisz trzy warstwy: główny HTML, dynamiczny endpoint wyspy i stan zastępczy widoczny przed podmianą.
- Główna strona może mieć agresywny cache publiczny, bo nie zawiera prywatnych danych.
- Wyspa z danymi użytkownika powinna mieć
Cache-Control: privatealbono-store. - Wyspa z danymi publicznymi, ale często zmiennymi, może mieć krótki cache, np.
s-maxage=60. - Do propsów przekazuj identyfikatory i małe wartości, a nie pełne rekordy z bazy.
- Stan zastępczy powinien zajmować tyle samo miejsca co finalna treść, żeby nie generować CLS.
Wydajność — czy to realnie szybsze?
Krótko: tak, ale nie zawsze. Server Islands wygrywają, kiedy:
- Większość strony jest statyczna i może być agresywnie cache'owana.
- Dynamiczny fragment jest mały (klient nie musi długo czekać na drugą odpowiedź).
- Cache'owanie na CDN daje realny zysk (dużo odwiedzin tej samej strony).
Nie wygrywają, kiedy:
- Cała strona i tak musi być SSR (np. dashboard).
- Dynamiczny fragment jest duży (np. cała lista 50 produktów) — wtedy drugie żądanie staje się wąskim gardłem.
- Strona ma ruch o niskiej częstotliwości (cache się nie opłaca).
Podsumowanie
Server Islands to elegancka odpowiedź na problem, który wraca w wielu projektach: większość strony może być statyczna, ale jeden fragment musi pozostać świeży. Zamiast wybierać między „wszystko SSG” a „wszystko SSR”, dostajesz kontrolę na poziomie konkretnego komponentu: statyczna powłoka trafia do cache CDN, a dynamiczne fragmenty są obsługiwane osobnym żądaniem.
Jeśli masz stronę w Astro, która powoli dryfuje w stronę SSR, bo dochodzą kolejne dynamiczne elementy, Server Islands mogą pomóc zachować statyczny fundament bez rezygnowania z personalizacji. Jeśli potrzebujesz pomocy w architekturze strony w Astro z mieszanymi wymaganiami statyki i dynamiki, napisz do mnie.
