W tym artykule rozbieram każdą z pięciu dyrektyw, pokazuję, kiedy której użyć i jakie błędy najczęściej spotykam w audytach stron Astro.
Kontekst — po co w ogóle dyrektywy hydracji
Astro domyślnie wysyła do przeglądarki zero JavaScriptu. Jeśli komponent (React, Vue, Svelte) ma być interaktywny, musisz jawnie wskazać, kiedy i jak ma pobrać swój kod JS i przejść . Brak domyślnego „wszystko hydratuj" to fundament architektury wysp — i jej największa przewaga.
Jeżeli nie wiesz, czym są wyspy w Astro, zacznij od wpisu o Islands Architecture.
Dyrektywa to kontrakt wydajnościowy — mówisz frameworkowi: „ten komponent otrzyma JS w taki a taki sposób". Astro renderuje wszystko najpierw do statycznego HTML, a dyrektywa decyduje, kiedy (lub czy w ogóle) ten HTML zostanie ożywiony przez JavaScript po stronie klienta.
client:load — hydracja natychmiast
client:load pobiera i uruchamia kod JavaScript komponentu jak najszybciej — gdy tylko przeglądarka przetworzy HTML. To najbardziej agresywna dyrektywa i powinna być zarezerwowana dla elementów, które muszą działać od razu.
Kiedy używać:
- Nawigacja główna z rozwijanym menu, które użytkownik prawdopodobnie otworzy natychmiast.
- Przycisk CTA w głównej sekcji (hero), który musi otworzyć okno modalne.
- Komponent do zmiany motywu (ciemny/jasny), który ma zareagować na preferencje użytkownika bez migotania strony.
Kiedy NIE używać:
- Formularze kontaktowe w stopce — do nich użytkownik musi przewinąć stronę, więc
client:visiblew zupełności wystarczy. - Komentarze pod wpisem — z tego samego powodu co wyżej.
- Galeria zdjęć, którą widać dopiero po kliknięciu w miniaturkę.
Kluczem do sukcesu jest selektywność. Każdy nieuzasadniony client:load to kilobajty blokujące i . Oznaczenie wszystkich wysp jako client:load niszczy całą przewagę wydajnościową Astro — i stawia Cię z powrotem na starcie Next.js, tyle że w innym ekosystemie.
client:idle — hydracja, kiedy przeglądarka jest bezczynna
client:idle czeka na wywołanie — moment, w którym przeglądarka zakończyła krytyczne zadania i procesor ma wolny cykl. W praktyce następuje to zazwyczaj od kilkuset milisekund do sekundy po załadowaniu strony.
Kiedy używać:
- Komponenty ważne, ale nie krytyczne dla pierwszej interakcji — zapis na newsletter, widżet czatu, baner zgody na pliki cookie (uwaga: RODO wymaga, by baner pojawił się przed załadowaniem innych skryptów śledzących).
- Skrypty analityczne i widżety dostawców zewnętrznych, które wpływają na interaktywność, ale nie stanowią priorytetu.
- Przyciski udostępniania w mediach społecznościowych.
Kiedy NIE używać:
- Elementy znajdujące się poza początkowo widocznym obszarem strony, których załadowanie można odłożyć używając
client:visible. - Krytyczne elementy interfejsu (okna modalne, główna nawigacja).
Dane pokazują, że różnica w czasie załadowania między client:idle a client:load wynosi 100–500 ms — i to właśnie te ułamki sekund decydują o TTI i wyniku Lighthouse.
client:visible — hydracja, kiedy komponent wchodzi w pole widzenia
client:visible wykorzystuje , aby pobrać i uruchomić JavaScript dopiero wtedy, gdy komponent pojawi się w widocznym obszarze ekranu. Jeśli użytkownik nie przewinie strony do tej sekcji — kod JS w ogóle się nie pobierze.
client:visible to domyślna rekomendacja dla wszystkich elementów poniżej linii przewijania. Jeśli użytkownik nie dotrze do sekcji — JavaScript nie załaduje się w ogóle.
Kiedy używać:
- Sekcja komentarzy pod artykułem.
- Formularz kontaktowy w stopce lub na samym dole strony.
- Galeria zdjęć znajdująca się poniżej opisu produktu.
- Kalkulator lub interaktywny widżet osadzony w środku wpisu.
- Karuzela z logotypami klientów.
Kiedy NIE używać:
- Komponenty na pierwszym ekranie — są one widoczne od razu, więc użycie
client:visibleniczego nie optymalizuje, a jedynie dokłada dodatkowy narzut związany z obserwatorem (IntersectionObserver). - Komponenty współdzielące stan z innymi wyspami — mechanizm obserwacji może wprowadzić zauważalne opóźnienie w synchronizacji danych.
Możesz też skonfigurować parametr client:visible, aby rozpocząć pobieranie kodu JS zanim komponent fizycznie wejdzie w widoczny obszar (prefetching):
Dzięki temu kod ładuje się, gdy komponent znajduje się np. 200 pikseli poniżej aktualnego widoku — użytkownik nie odczuje żadnego opóźnienia, a w przypadku gdy w ogóle tam nie przewinie, oszczędzamy zasoby sieciowe.
client:media — hydracja tylko przy spełnieniu warunków media query
client:media ożywia komponent tylko wtedy, gdy przeglądarka spełnia przekazane reguły zapytania o media (media query). Na smartfonie DesktopSidebar nigdy nie pobierze swojego kodu JS, podobnie jak MobileNav na komputerze stacjonarnym.
Kiedy używać:
- Elementy interfejsu przeznaczone wyłącznie na urządzenia mobilne — menu typu hamburger, wysuwane panele dolne (bottom sheets), galerie obsługujące gesty przesunięcia (swipe).
- Elementy wyłącznie desktopowe — rozbudowane menu rozwijane po najechaniu kursorem, skomplikowane filtry wykorzystujące mechanizm przeciągnij i upuść.
- Responsywne widżety, które mają kompletnie inną logikę działania w zależności od rozmiaru ekranu.
Kiedy NIE używać:
- Kiedy komponent dostosowuje się tylko wizualnie (za pomocą CSS media queries), ale nie zmienia logiki biznesowej.
- Gdy zachowanie różni się zaledwie szczegółem — prościej jest użyć
client:visiblei wewnątrz komponentu weryfikować warunki przezwindow.matchMedia.
Po tę dyrektywę sięgam rzadko, ale w specyficznych sytuacjach — np. przy ciężkim wysuwanym panelu mobilnym, który na desktopie nie istnieje — oszczędza dziesiątki kilobajtów transferu. Wdrażamy ją tylko wtedy, gdy logika po obu stronach ekranu jest fundamentalnie inna.
client:only — komponent wyłącznie po stronie klienta
client:only to sygnał dla Astro: „nie próbuj renderować tego komponentu po stronie serwera (), wygeneruj go wyłącznie w przeglądarce". Działa to odwrotnie do pozostałych dyrektyw.
Kiedy używać:
- Komponenty zależne w fazie renderowania od obiektów globalnych przeglądarki takich jak
window,documentczylocalStorage— bez tego proces SSR zakończyłby się błędem. - Biblioteki, które nie posiadają wsparcia dla SSR (np. niektóre nakładki na Three.js, react-leaflet, edytory tekstu typu WYSIWYG).
- Komponenty bazujące na danych z bazy
IndexedDBlub service workerów. - Elementy, których wygląd jest bardzo mocno uzależniony od dokładnego rozmiaru okna, a wersja wyrenderowana na serwerze i tak wymagałaby natychmiastowego przebudowania przez JS.
Kiedy NIE używać:
- We wszystkich innych przypadkach. Użycie
client:onlydezaktywuje mechanizm SSR, przez co rezygnujesz z błyskawicznego serwowania gotowej treści. Zamiast tego zmuszasz użytkownika do oczekiwania, aż pobierze się JS i wygeneruje komponent bezpośrednio w jego przeglądarce.
Sprawdzoną praktyką przy korzystaniu z client:only jest dodanie zastępczego szkieletu (placeholdera):
Dzięki temu zabiegowi użytkownik na czas wczytywania widzi zarezerwowaną przestrzeń, układ strony nie „skacze", a wskaźnik przesunięcia układu () pozostaje nienaruszony.
Porównanie w tabeli
| Dyrektywa | Kiedy ładuje JS | Kiedy używać | Kiedy unikać |
|---|---|---|---|
client:load | Natychmiast | Krytyczne interakcje na pierwszym ekranie (nawigacja, główne przyciski) | Elementy widoczne dopiero po przewinięciu |
client:idle | Gdy przeglądarka jest bezczynna | Ważne, ale nie priorytetowe elementy (newsletter, czat) | Krytyczny interfejs, komponenty reagujące na przewijanie |
client:visible | Gdy element wchodzi w pole widzenia | Wszystko poniżej pierwszego ekranu | Elementy widoczne od razu po załadowaniu |
client:media | Gdy spełnione są reguły media query | Interfejsy specyficzne tylko dla mobile / desktop | Gdy zmienia się wyłącznie wygląd, a nie logika |
client:only | Po załadowaniu strony (omija SSR) | Biblioteki niekompatybilne z SSR, wymagające okna przeglądarki | Każdy element, który można bez problemu wyrenderować na serwerze |
Budżet hydracji
W większych projektach wdrażam limit wielkości kodu (budżet hydracji) dla każdego typu komponentów. To chroni przed pułapką, w której strona Astro powinna być szybka, a w praktyce ładuje kilka masywnych paczek.
- maksymalna liczba wysp z client:load na pierwszym ekranie
- 1–2maksymalna liczba wysp z client:load na pierwszym ekranie
- JavaScript dla elementów czysto wizualnych bez interakcji
- 0 KBJavaScript dla elementów czysto wizualnych bez interakcji
- Komponenty widoczne od razu po załadowaniu: maksymalnie 1–2 interaktywne wyspy z
client:load. - Sekcje poniżej linii przewijania: zawsze
client:visiblejako domyślny wybór. - Detale wizualne i dekoracje: brak hydracji, chyba że wprost wpływają na konwersję.
- Komponenty wymagające API przeglądarki:
client:only— brak SSR jest w tym wypadku nieunikniony. - Współdzielone biblioteki: regularna weryfikacja, czy jeden mały komponent nie importuje całej biblioteki wykresów, edytora WYSIWYG albo kitu.
Najczęstsze błędy
W audytach stron Astro notorycznie spotykam trzy te same błędy:
1. Nadużywanie client:load. Wytłumaczenie zawsze brzmi: „bo po prostu działa". Serwis z ośmioma komponentami oznaczonymi client:load traci całą przewagę nad Next.js — staje się identycznym tworem, tyle że w innym ekosystemie.
2. Layout owinięty w jeden wielki React z client:load. Programista przyzwyczajony do Next.js odruchowo buduje Layout.tsx z nagłówkiem, treścią i stopką — i oznacza całość client:load. Fundament strony musi być .astro. Frameworkowe komponenty dodajemy jak karabinowe gniazda w mocnych punktach — wyłącznie tam, gdzie konieczna jest interakcja.
3. client:only bez elementu zastępczego. Komponent ładuje się po 1,5 s, strona skacze, CLS rośnie. Zawsze ustaw kontener zastępczy z odpowiednią wysokością na czas ładowania.
Scenariusz praktyczny — karta produktu w e-commerce
Przeanalizujmy dobór odpowiednich dyrektyw przy projektowaniu standardowej podstrony produktowej:
Taka konfiguracja gwarantuje, że:
- Otrzymujemy natychmiastowe wyświetlenie pełnej struktury strony (bez oczekiwania na pobranie skryptów).
- Krytyczne strefy interfejsu (galeria zdjęć, przycisk zakupu) są błyskawicznie hydratowane i gotowe do akcji.
- Skrypty opinii ładują się tylko i wyłącznie, gdy użytkownik przewinie stronę do danej sekcji.
- Elementy o niższym priorytecie (jak karuzela sugerująca inne produkty) nie opóźniają pierwszego renderowania zawartości na ekranie.
Audyt własnej strony Astro
Jeśli rozwijasz już projekt w Astro, wdróż ten czteropunktowy audyt:
- Przeszukaj kod pod kątem
client:load— każda taka deklaracja musi być nieodzowna na pierwszym ekranie. - Zmień na
client:visiblekażdą dyrektywę dla elementów poza pierwszym ekranem. - Znajdź każde
client:only— udokumentuj komentarzem, dlaczego SSR jest tu niemożliwy. Część przypadków da się przepisać. - Uruchom Lighthouse Mobile. TBT poniżej 200 ms, TTI maksymalnie 3,5 s na wolnym 4G.
Jeśli chcesz zlecić profesjonalny audyt SEO i wydajności Twojej witryny w Astro — wejdź na wyższy poziom i odezwij się.
