Architektura wysp to wzorzec rozdzielający dokument HTML od niezależnych obszarów interaktywnych. Astro wymaga jawnego włączenia hydratacji, co utrudnia przypadkowe wysłanie całego drzewa frameworka do klienta. Nadal trzeba jednak optymalizować obrazy, fonty, CSS, skrypty zewnętrzne, cache i kod samych wysp.
Skąd wzięła się Islands Architecture?
Pojęcie zostało ukute w 2019 roku przez Katie Sylor-Miller, architektkę frontendu Etsy, a później rozwinięte przez Jasona Millera, twórcę Preacta, w jego artykule z 2020 roku. Idea jest pozornie prosta: renderuj stronę jako HTML na serwerze, a w obszarach, które faktycznie potrzebują interaktywności, umieść niezależne komponenty hydratowane osobno.
W klasycznym cała aplikacja bywa jednym drzewem klienckim. Przeglądarka pobiera jego JavaScript, uruchamia framework i dopiero wtedy może obsłużyć interakcje. SSR potrafi wcześniej pokazać HTML, ale nie usuwa kosztu hydratacji klienta. Gdy kod dotrze za późno, widoczny przycisk może jeszcze nie reagować.
Nie należy przenosić tego opisu jeden do jednego na każdy współczesny metaframework. W Next.js App Router layouty i strony są domyślnie Server Components, a JavaScript hydratuje Client Components wyznaczone granicą 'use client'. Next przesyła również payload RSC i obsługuje nawigację po stronie klienta. Astro wybiera inny model: dokument może pozostać klasyczną stroną MPA, a każdy komponent frameworka dostaje klienta dopiero po dodaniu dyrektywy client:*.
Islands Architecture odwraca ten model — strona jest domyślnie statycznym HTML-em, a interaktywność to wyjątek, który aktywnie deklarujesz.
Jak Islands Architecture działa w Astro?
Weźmy typową stronę firmową z nagłówkiem, hero, sekcją usług, formularzem i stopką. W klienckim SPA wszystkie elementy mogą znaleźć się w jednym hydratowanym drzewie. Next.js App Router pozwala ograniczyć klienta granicami Client Components. W Astro punktem wyjścia są komponenty renderowane do HTML, a formularz może stać się osobną wyspą.
W Astro piszesz to tak:
Header, Hero, Services i Footer to komponenty .astro — renderują się do HTML-u podczas builda lub na żądanie. Kod z frontmatteru nie trafia do klienta, choć jawny <script> w komponencie nadal trafi. ContactForm jest komponentem React z client:visible, więc jego kod zostanie pobrany i zhydratowany, gdy obszar wejdzie w viewport.
HTML formularza może być widoczny wcześniej dzięki renderowaniu serwerowemu, ale obsługa React zacznie działać dopiero po hydratacji. Dlatego komponent powinien mieć natywne zachowanie zastępcze albo zostać zhydratowany odpowiednio wcześnie. client:visible={{ rootMargin: '200px' }} może rozpocząć pracę przed wejściem sekcji na ekran.
Zero JS domyślnie w Astro: co to naprawdę znaczy?
W Astro komponent frameworka bez client:* jest renderowany do HTML-u bez wysłania jego kodu klienckiego. Strona może więc mieć 0 KB własnego JavaScriptu, o ile nie zawiera skryptów, routera przejść, wysp klienckich ani integracji dodających kod w przeglądarce. To właściwość wyniku builda, którą warto potwierdzić w panelu Network, a nie gwarancja dla każdego projektu Astro.
Brak runtime'u ogranicza parsowanie i wykonywanie JavaScriptu, co może pomóc responsywności oraz . Nie gwarantuje jednak wyniku Lighthouse ani zaliczenia : może zepsuć ciężki obraz lub wolny serwer, CLS — fonty i reklamy, a INP — kod zewnętrznego widżetu. Wydajność oceniaj na danych terenowych i reprezentatywnych podstronach.
Dyrektywy hydratacji w Astro jako kontrakt wydajności
Kiedy komponent frameworka musi być interaktywny, Astro pozwala określić, kiedy zacznie pobierać i hydratować JavaScript. Dyrektywa jest dostępna dla komponentu UI bezpośrednio importowanego do pliku .astro, a jej wybór powinien wynikać z najwcześniejszej możliwej interakcji:
client:load— ładuje i hydratuje komponent możliwie szybko. Dla UI, którego użytkownik może potrzebować natychmiast, niezależnie od położenia na stronie.client:idle— czeka na , a przy braku jego obsługi na zdarzenieload. Opcjatimeoutpozwala ograniczyć maksymalne opóźnienie.client:visible— używa . OpcjonalnyrootMarginrozpoczyna hydratację przed faktycznym wejściem komponentu w viewport.client:media="(max-width: 50em)"— hydratuje, kiedy media query pasuje. Dla UI przeznaczonego wyłącznie na określony wariant ekranu.client:only="react"— pomija , dlatego Astro wymaga wskazania frameworka, np.reactlubvue. Używaj tylko wtedy, gdy komponentu nie da się wyrenderować na serwerze; treść nie znajdzie się w początkowym HTML-u.
Opóźniona hydratacja może poprawić początkowe ładowanie, ale nie może tworzyć martwego interfejsu. Testuj szybkie przewijanie i kliknięcie przed hydratacją na wolnym połączeniu oraz słabszym telefonie. Dla linków i formularzy preferuj natywne HTML jako działający fundament, a JavaScript traktuj jako ulepszenie.
Szczegółowo rozbieram każdą z nich w artykule o client directives w Astro.
Hydratacja musi odtworzyć ten sam interfejs
Komponent frameworka jest najpierw renderowany do HTML-u, a następnie uruchamiany ponownie w przeglądarce. Początkowy wynik obu środowisk powinien być zgodny. Losowa wartość, bieżąca data, szerokość okna lub dane z localStorage użyte bez zabezpieczenia mogą wywołać hydration mismatch albo nagłą zmianę treści.
Przekazuj do wyspy możliwie małe, serializowalne propsy. Dane zależne od przeglądarki odczytuj po uruchomieniu komponentu, ale zaprojektuj stabilny stan początkowy. client:only usuwa problem zgodności przez rezygnację z SSR, lecz ceną jest brak właściwej treści w początkowym HTML-u — nie powinien być automatycznym rozwiązaniem każdego ostrzeżenia.
Komponenty z różnych frameworków na jednej stronie Astro
Architektura wysp ma jeszcze jedną konsekwencję, która w praktyce okazuje się bardziej użyteczna, niż się wydaje na pierwszy rzut oka — każda wyspa jest niezależna, więc może być napisana w innym frameworku.
W tradycyjnej SPA takie połączenie byłoby trudne do utrzymania, bo framework jest zwykle jeden. W Astro każda wyspa może używać własnego frameworka, ale nie oznacza to darmowego mieszania technologii. React, Vue i Svelte wnoszą oddzielne runtime'y, integracje, konwencje testowania i zależności. Bundler może współdzielić chunki między wyspami tego samego frameworka, więc nie każda wyspa jest osobną, całkowicie zduplikowaną paczką.
Mieszanie frameworków ma sens przede wszystkim podczas stopniowej migracji albo przy ponownym wykorzystaniu trudnego do zastąpienia komponentu. W nowym projekcie jeden framework kliencki zwykle upraszcza zależności, dostępność, testy i współdzielenie stanu. Zanim dodasz kolejny runtime, porównaj koszt integracji z kosztem przepisania komponentu.
Server Islands i dynamiczne fragmenty statycznej strony
Server Islands rozwiązują inny problem niż selektywna hydratacja. Komponent z server:defer nie renderuje się razem z główną stroną; przeglądarka otrzymuje fallback, a następnie mały skrypt pobiera osobno HTML wygenerowany na serwerze. Mechanizm pojawił się eksperymentalnie w Astro 4.12, ale w aktualnym projekcie kieruj się dokumentacją używanej wersji, a nie historycznym numerem wydania.
Główna strona może być prerenderowana lub renderowana na żądanie, a dynamiczny fragment — np. stan magazynu albo spersonalizowany avatar — dociera osobnym żądaniem. Komponent serwerowy nie wymaga runtime'u frameworka do hydratacji, ale Server Island nie oznacza zerowego kosztu: dochodzi endpoint, round trip, skrypt podmiany, fallback oraz obsługa błędu. Cache i personalizację konfigurujesz zgodnie z danymi; odpowiedzi zależnej od cookies nie wolno przypadkowo udostępnić innym użytkownikom.
Server Islands wymagają adaptera obsługującego renderowanie na żądanie. Testuj je na docelowym hostingu, zwłaszcza pod kątem cookies, nagłówków cache, opóźnienia regionu, timeoutów i działania fallbacku bez odpowiedzi endpointu.
Szerzej opisuję ten mechanizm w artykule o Server Islands w Astro.
Kiedy Islands Architecture daje realne korzyści?
Architektura wysp pomaga przede wszystkim wtedy, gdy struktura produktu odpowiada granicom niezależnej interaktywności:
- Strona jest głównie treścią. Blog, dokumentacja, strona firmowa, portfolio lub landing page składają się przede wszystkim z tekstu, obrazów, linków i formularzy, które mogą działać bez rozbudowanego stanu klienta.
- Interaktywność ma wyraźne granice. Kalkulator, wyszukiwarka, menu i karuzela mogą działać niezależnie, bez wspólnego drzewa obejmującego cały layout.
- Koszt JavaScriptu jest realnym problemem. Profilowanie pokazuje długie zadania, wysokie użycie CPU albo opóźnione INP powodowane kodem aplikacji, a nie wyłącznie obrazami, serwerem czy zewnętrznymi skryptami.
- Zespół akceptuje model MPA. Nawigacja dokumentowa, URL jako źródło stanu i progresywne ulepszanie pasują do produktu oraz oczekiwanego UX.
Kiedy Islands Architecture nie pomaga?
I druga strona medalu:
- Większość ekranu tworzy jeden stanowy workflow. Edytor, rozbudowany dashboard lub narzędzie projektowe może być prostsze jako jedna większa aplikacja niż kilkanaście sztucznie rozdzielonych korzeni.
- Komponenty stale wymieniają stan. Wyspy potrafią komunikować się przez store lub serwer, ale duża liczba dwukierunkowych zależności jest sygnałem, że granice zostały postawione w niewłaściwym miejscu.
- Produkt zakłada intensywną nawigację kliencką i jeden ekosystem React. Next.js może lepiej pasować do zespołu korzystającego z RSC, Client Components i bibliotek wymagających wspólnego drzewa. Nie dlatego, że Astro nie ma backendu: Astro oferuje endpointy, middleware, Actions i renderowanie na żądanie. Różnią się dojrzałość integracji, model wdrożenia i ergonomia konkretnego przypadku.
- Główne koszty leżą poza kodem frameworka. Jeżeli wydajność ograniczają reklamy, tag manager, fonty, obrazy lub wolne API, samo rozbicie komponentów na wyspy nie usunie problemu.
Porównanie obu podejść szerzej opisałem w artykule Astro.js vs Next.js — które narzędzie wybrać w 2026 roku?.
Praktyczne wskazówki dla projektowania wysp w Astro
Jeśli zaczynasz projekt w Astro, rekomenduję następujący sposób myślenia:
Zaczynaj od działającego HTML-u. Nawigacja, link, formularz i element <details> często zapewniają podstawową funkcję bez frameworka. Po React, Vue lub Svelte z hydratacją sięgaj wtedy, gdy potrzebujesz stanu, złożonych zdarzeń albo biblioteki UI. Mały <script> w komponencie Astro może być prostszy niż cały runtime frameworka.
Wybieraj dyrektywę według interakcji. Nie przyjmuj client:visible jako automatycznego wyboru. Menu widoczne od początku może wymagać client:load, ciężka karuzela niżej — client:visible z rootMargin, a widget bez pilnej interakcji — client:idle z limitem czasu. CTA będące zwykłym linkiem nie wymaga hydratacji.
Nie zawijaj całego layoutu w React. To typowy błąd przy migracji z Next.js — programista przyzwyczajony do _app.tsx opakowuje wszystko w jeden komponent React. W Astro layout powinien być .astro, a Reacta używasz tylko w miejscach, które naprawdę potrzebują interakcji.
Nie twórz wyspy dla każdego wiersza bez pomiaru. Sto niezależnych korzeni ma koszt uruchamiania i zarządzania, nawet gdy bundler współdzieli runtime. Jeśli elementy wspólnie filtrują się lub sortują, jeden kontener może być prostszy. Gdy są niezależne i rzadko widoczne, kilka mniejszych granic może opóźnić niepotrzebny kod — decyzję potwierdź profilem.
Projektuj jawny przepływ stanu. React Context działa w obrębie jednej wyspy React, nie między osobnymi korzeniami. Do prostego stanu między wyspami możesz użyć , URL-a lub zdarzeń DOM. Danych biznesowych nie duplikuj bez kontroli w kilku klientach — ustal źródło prawdy i sposób synchronizacji z serwerem.
Testuj moment przed hydratacją. Wyłącz JavaScript, włącz wolne łącze i throttling CPU, a następnie kliknij element natychmiast po jego pojawieniu się. Sprawdź focus, klawiaturę, komunikaty formularza, stabilność layoutu i to, czy fallback nie wygląda jak aktywny przycisk, gdy jeszcze nim nie jest.
Budżet JavaScriptu dla wysp Astro
Dyrektywa client:* jest decyzją o budżecie i czasie interaktywności. Wyspa wnosi kod komponentu oraz zależności, ale bundler może wydzielić współdzielone chunki, więc nie licz kosztu przez proste mnożenie liczby wysp. Sprawdź początkowy JavaScript, kod pobrany po scrollu, coverage, długie zadania i INP. Porównaj zimne wejście z nawigacją wewnętrzną oraz urządzenie klasy średniej zamiast wyłącznie szybkiego laptopa.
| Typ sekcji | Domyślna decyzja | Dlaczego |
|---|---|---|
| Hero z tekstem i obrazem | .astro, bez hydratacji | Treść i układ nie potrzebują JS |
| Formularz kontaktowy | HTML + Astro Action; JS opcjonalnie | Może działać bez hydratacji, a JS ulepsza walidację |
| Menu mobilne | Mały skrypt lub wyspa z client:load | Nawigacja musi działać od pierwszej interakcji |
| Kalkulator ceny | client:visible z rootMargin | Powinien być gotowy, zanim użytkownik do niego dotrze |
| Opinie, logo, FAQ | Statyczny HTML | Interaktywność zwykle nie wnosi wartości |
Islands Architecture a SEO
Z perspektywy SEO architektura wysp ułatwia umieszczenie kluczowej treści, linków i metadanych w początkowym HTML-u. Google potrafi renderować JavaScript, ale ważna treść nie powinna zależeć wyłącznie od hydratacji wyspy. client:only zastosowany do głównego artykułu lub listy produktów usuwa ich właściwy HTML z pierwszej odpowiedzi i pogarsza odporność strony na błąd skryptu.
Gotowy HTML nie tworzy automatycznie poprawnego SEO. Nadal odpowiadasz za statusy HTTP, linki kanoniczne, robots, linkowanie, dane uporządkowane, hreflang, sitemapę i zgodność treści wyspy serwerowej z zasadami cache. Mniejszy koszt JavaScriptu może pomóc wydajności, ale framework nie gwarantuje rankingu, indeksacji ani cytowania przez system AI.
Głębiej temat SEO w Astro rozbieram w osobnym artykule.


