StriveLab
Strony internetowe
Usługi
RealizacjeO mnieBlogPorozmawiajmy
PL
EN
StriveLab
Strony internetowe
Usługi
RealizacjeO mnieBlogPorozmawiajmy
PL
EN

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

QA & Automation

Testy automatyczne komponentów i E2E w oparciu o Cypress.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

RealizacjeO mnieBlog
Porozmawiajmy
PL
EN

Nowoczesne strony internetowe dla firm, które myślą odważnie.

Przewiń do góry

Nazwa

StriveLab Maciej Sala

NIP

6772218995

REGON

524008527

E-mail

contact@strivelab.pl

Usługi główne
  • Tworzenie stron internetowych
  • Strony internetowe Next.js
  • Strony internetowe Astro
  • Strony internetowe React
Inne usługi
  • Usługi
  • SEO & Performance Sprint
  • QA & Stabilizacja
  • Konsultacje Product / Delivery
  • Aplikacje webowe Next.js
  • Współpraca ciągła
Strony
  • O mnie
  • Usługi
  • Realizacje
  • Blog

© 2026 StriveLab.pl

Polityka prywatności
AstroHydrationPerformance

Client directives w Astro — client:load, client:idle, client:visible, client:media, client:only w praktyce

Kiedy użyć której dyrektywy hydracji w Astro? Szczegółowe porównanie client:load, client:idle, client:visible, client:media i client:only — z przykładami, benchmarkami i typowymi błędami.

OpublikujLinkedInFacebookWyślij
Autor
Maciej Sala
Opublikowano
1 maja 2026 16:31
Czytanie
9 min czytania
Aktualizacja
30 kwietnia 2026 11:16

W skrócie

  • client:load zostaw dla interakcji krytycznych na pierwszym ekranie (w początkowo widocznym obszarze).
  • client:visible jest najczęściej najlepszym wyborem dla komponentów znajdujących się niżej na stronie.
  • client:idle pomaga przesunąć mniej pilny JavaScript poza krytyczną ścieżkę renderowania.
  • client:only usuwa SSR dla komponentu, więc używaj go tylko przy realnej zależności od API przeglądarki.

Dyrektywy hydracji (client:*) to jedno z najważniejszych narzędzi w Astro — i jednocześnie jedno z tych, które początkujący najczęściej stosują niewłaściwie. Różnica między client:load a client:visible to nie jest kwestia kosmetyczna; ma ona realny wpływ na metryki Core Web Vitals oraz odczucia użytkownika (User Experience).

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. To świadoma decyzja projektowa — nie ma domyślnego „wszystko hydratuj", bo to by niszczyło całą ideę architektury wysp.

Jeżeli nie wiesz, czym są wyspy w Astro, zacznij od wpisu o Islands Architecture.

Dyrektywa Dyrektywy client:* w Astro określają, kiedy komponent frameworkowy ma pobrać kod JavaScript i stać się interaktywny w przeglądarce. 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

Code
---
import Navbar from '../components/Navbar.tsx';
---
 
<Navbar client:load />

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:visible w 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ę.

Koszt użycia client:load to dodatkowe kilobajty wpływające negatywnie na metryki Total Blocking Time (TBT) i Time to Interactive (TTI). Jeśli bez zastanowienia oznaczysz wszystkie wyspy jako client:load, stracisz całą przewagę wydajnościową Astro.

client:idle — hydracja, kiedy przeglądarka jest bezczynna

Code
---
import NewsletterSignup from '../components/NewsletterSignup.tsx';
---
 
<NewsletterSignup client:idle />

client:idle czeka na wywołanie requestIdleCallback — 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).

Różnica w czasie załadowania między client:idle a client:load to zwykle od 100 do 500 ms, jednak to właśnie te ułamki sekund mają decydujący wpływ na TTI oraz wynik wydajności w Lighthouse.

client:visible — hydracja, kiedy komponent wchodzi w pole widzenia

Code
---
import CommentsSection from '../components/CommentsSection.tsx';
import ProductGallery from '../components/ProductGallery.tsx';
---
 
<article>
  <!-- długa treść artykułu -->
</article>
 
<CommentsSection client:visible />

client:visible wykorzystuje API IntersectionObserver, 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.

To najbardziej oszczędna dyrektywa i moja domyślna rekomendacja dla wszystkich elementów znajdujących się poza pierwszym ekranem (poniżej linii przewijania).

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:visible niczego 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):

Code
<CommentsSection client:visible={{ rootMargin: "200px" }} />

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

Code
---
import MobileNav from '../components/MobileNav.tsx';
import DesktopSidebar from '../components/DesktopSidebar.tsx';
---
 
<MobileNav client:media="(max-width: 768px)" />
<DesktopSidebar client:media="(min-width: 1024px)" />

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:visible i wewnątrz komponentu weryfikować warunki przez window.matchMedia.

Jest to dyrektywa, po którą sięgam stosunkowo rzadko, lecz w specyficznych sytuacjach (np. przy ważącym dużo wysuwanym panelu na telefonach, który w ogóle nie jest renderowany na desktopie) pozwala zaoszczędzić dziesiątki kilobajtów transferu.

client:only — komponent wyłącznie po stronie klienta

Code
---
import ChartWidget from '../components/ChartWidget.tsx';
import ClientSideMap from '../components/InteractiveMap.tsx';
---
 
<ChartWidget client:only="react" />
<ClientSideMap client:only="react" />

client:only to sygnał dla Astro: „nie próbuj renderować tego komponentu po stronie serwera (SSR), 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, document czy localStorage — 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 IndexedDB lub 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:only dezaktywuje 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):

Code
<div class="min-h-[400px] flex items-center justify-center">
  <ClientSideMap client:only="react">
    <p slot="fallback">Ładowanie mapy...</p>
  </ClientSideMap>
</div>

Dzięki temu zabiegowi użytkownik na czas wczytywania widzi zarezerwowaną przestrzeń, układ strony nie „skacze", a wskaźnik przesunięcia układu (CLS) pozostaje nienaruszony.

Porównanie w tabeli

DyrektywaKiedy ładuje JSKiedy używaćKiedy unikać
client:loadNatychmiastKrytyczne interakcje na pierwszym ekranie (nawigacja, główne przyciski)Elementy widoczne dopiero po przewinięciu
client:idleGdy przeglądarka jest bezczynnaWażne, ale nie priorytetowe elementy (newsletter, czat)Krytyczny interfejs, komponenty reagujące na przewijanie
client:visibleGdy element wchodzi w pole widzeniaWszystko poniżej pierwszego ekranuElementy widoczne od razu po załadowaniu
client:mediaGdy spełnione są reguły media queryInterfejsy specyficzne tylko dla mobile / desktopGdy zmienia się wyłącznie wygląd, a nie logika
client:onlyPo załadowaniu strony (omija SSR)Biblioteki niekompatybilne z SSR, wymagające okna przeglądarkiKażdy element, który można bez problemu wyrenderować na serwerze

Budżet hydracji

W większych projektach wprowadzam limit wielkości wczytywanego kodu (budżet hydracji) dla każdego z typów komponentów. Takie podejście chroni przed sytuacją, w której strona na Astro teoretycznie powinna być szybka, a w praktyce i tak ładuje kilka masywnych paczek kodu.

  • Komponenty widoczne od razu po załadowaniu: dozwolona maksymalnie 1-2 interaktywne wyspy z dyrektywą client:load.
  • Sekcje widoczne po przewinięciu strony: zawsze domyślne użycie client:visible.
  • Detale wizualne i dekoracje: całkowity brak hydracji, chyba że ewidentnie wpływają one na lepszą konwersję.
  • Komponenty wymagające API przeglądarki: client:only, z zaznaczeniem, że brak SSR jest w tym przypadku nie do ominięcia.
  • Współdzielone biblioteki: regularna weryfikacja, czy jeden niewielki komponent nagle nie importuje obszernej biblioteki do rysowania wykresów, edytora tekstu czy ogromnego zestawu gotowych elementów interfejsu (UI kit).
Top tip

Praktyczna zasada: jeśli element na stronie nie wymaga nasłuchiwania na kliknięcia, wpisywania tekstu, reakcji na zmianę rozmiaru okna lub specyficznych danych z przeglądarki klienta — prawdopodobnie w ogóle nie potrzebuje kodów JS i hydracji.

Najczęstsze błędy

W trakcie audytów witryn stworzonych w Astro notorycznie spotykam trzy problemy:

1. Nadużywanie client:load. Najczęstsze wytłumaczenie: „dzięki temu po prostu działa". To jednocześnie najszybsza droga do pogrzebania wysokiej wydajności. Serwis internetowy z ośmioma komponentami oznaczonymi client:load traci przewagę nad stronami opartymi np. o Next.js, stając się identycznym tworem, tyle że w innym ekosystemie.

2. Obejmowanie całego układu (layoutu) w jeden wielki React z client:load. Programista pracujący wcześniej głównie z Next.js odruchowo buduje bazowy plik Layout.tsx, tam importuje nagłówek, główną treść, stopkę i dodaje parametr client:load do całości. Fundamentem każdej strony powinien być szablon w czystym .astro, a frameworkowe komponenty należy dorzucać jak przyprawy – wyłącznie w miejscach autentycznej interakcji.

3. Pozostawienie client:only bez elementu zastępczego. Komponent wczytuje się dopiero po półtorej sekundy opóźnienia, co wywołuje skok całej reszty strony i tym samym wskaźnik CLS drastycznie rośnie. Pamiętaj, aby zawsze ustawiać kontener zastępczy zachowujący odpowiednią wysokość na czas załadowania.

Scenariusz praktyczny — karta produktu w e-commerce

Przeanalizujmy dobór odpowiednich dyrektyw przy projektowaniu standardowej podstrony produktowej:

Code
---
// src/pages/produkt/[slug].astro
import Layout from '../../layouts/Layout.astro';
import Header from '../../components/Header.astro';
import ProductImages from '../../components/ProductImages.tsx';
import AddToCart from '../../components/AddToCart.tsx';
import ProductDescription from '../../components/ProductDescription.astro';
import Reviews from '../../components/Reviews.tsx';
import RecentlyViewed from '../../components/RecentlyViewed.tsx';
import Footer from '../../components/Footer.astro';
 
const { product } = Astro.props;
---
 
<Layout>
  <Header />
 
  <main>
    <!-- Galeria widoczna od razu, istnieje wysokie prawdopodobieństwo wejścia w interakcję -->
    <ProductImages images={product.images} client:load />
 
    <!-- Przycisk dodawania do koszyka (CTA) o kluczowym znaczeniu dla konwersji -->
    <AddToCart productId={product.id} client:load />
 
    <!-- Czysto statyczny tekst opisu, nie generuje JS -->
    <ProductDescription content={product.description} />
 
    <!-- Sekcja opinii umieszczona niżej, aktywuje się dopiero przy przewijaniu -->
    <Reviews productId={product.id} client:visible />
 
    <!-- Karuzela "Ostatnio przeglądane" pobiera kod JS w wolnej chwili -->
    <RecentlyViewed client:idle />
  </main>
 
  <Footer />
</Layout>

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 korzystając z tego frameworka, polecam wykonać prosty audyt:

  1. Przeszukaj kod pod kątem client:load i upewnij się, czy każda taka deklaracja rzeczywiście jest nieodzowna na pierwszym ekranie.
  2. Zmień na client:visible każdą dyrektywę dla elementów znajdujących się poza pierwszym ekranem.
  3. Poszukaj miejsc wykorzystania client:only – być może część dałoby się wyrenderować przez SSR. Użycie tej dyrektywy powinno być udokumentowane (np. komentarzem „biblioteka X nie wspiera SSR").
  4. Uruchom narzędzie Lighthouse (na urządzeniach mobilnych). Wynik TBT powinien znajdować się poniżej 200 ms, a czas TTI wynosić maksymalnie 3,5 s na spowolnionym łączu 4G.

Jeśli chcesz zlecić profesjonalny audyt SEO i wydajności Twojej witryny oparty o technologię Astro — chętnie podejmę się tego zadania.

Podsumowanie

Dyrektywy client:* to precyzyjne narzędzie do optymalizacji wydajności. Nie istnieje jedna idealna, domyślna dyrektywa — każda z nich rozwiązuje inny problem i wiąże się z innymi kosztami. Praktyczna zasada, której sam się trzymam, to traktowanie client:visible jako domyślnego wyboru, używanie client:idle dla ważnych, lecz niepilnych elementów na pierwszym ekranie, client:load dla interfejsu krytycznego, a client:only w sytuacjach, gdy wsparcie dla renderowania po stronie serwera jest fizycznie niemożliwe.

Jeśli nie masz pewności, czy podział Twoich komponentów na wyspy jest optymalny, napisz do mnie — chętnie rzucę okiem na architekturę projektu i wskażę obszary do poprawy.

Często zadawane pytania

`client:idle` ładuje JS, kiedy przeglądarka ma wolny cykl (zazwyczaj 100–500 ms po starcie), niezależnie od pozycji komponentu na stronie. `client:visible` ładuje JS dopiero, gdy komponent wchodzi w widoczny obszar ekranu (viewport) — jeśli użytkownik nie przewinie do niego, JS nie załaduje się w ogóle.

Pracuję z tym zawodowo.

Jeśli chcesz przełożyć ten temat na lepszą architekturę frontendu, uporządkować React lub Next.js i podnieść jakość pracy zespołu, skontaktuj się ze mną. Pomagam zamieniać wiedzę z artykułów w praktyczne decyzje technologiczne.

Skontaktuj się ze mną
Maciej Sala

O autorze

Maciej Sala

Maciej Sala — project manager i frontendowiec z doświadczeniem w marketingu internetowym. Na co dzień pracuję z Reactem, Next.js i TypeScriptem, łącząc perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat związany z branżą gier wideo jako project manager i game designer.

Absolwent historii na Uniwersytecie Jagiellońskim i studiów podyplomowych z marketingu internetowego na Akademii Górniczo-Hutniczej w Krakowie. Poza pracą trenuje na siłowni, maluje figurki i realizuje własne projekty.

Moje artykułyWięcej o mnie

Seria

Astro w praktyce 2026
  1. 1Astro 6 — przewodnik po nowościach: Cloudflare Workers, Live Content Collections, Fonts API i CSP
  2. 2Architektura wysp w Astro — czym są wyspy i dlaczego zero JS domyślnie zmienia zasady gry
  3. 3SEO w Astro — Core Web Vitals, dane uporządkowane i techniczny fundament rankingu w 2026
  4. 4Migracja bloga z WordPress na Astro — eksport treści, przekierowania 301 i zachowanie pozycji w Google

Spis treści

12 sekcji · 12 min

  • Kontekst — po co w ogóle dyrektywy hydracji1 min
  • client:load — hydracja natychmiast1 min
  • client:idle — hydracja, kiedy przeglądarka jest bezczynna1 min
  • client:visible — hydracja, kiedy komponent wchodzi w pole widzenia1 min
  • client:media — hydracja tylko przy spełnieniu warunków media query1 min
  • client:only — komponent wyłącznie po stronie klienta1 min
  • Porównanie w tabeli1 min
  • Budżet hydracji1 min
  • Najczęstsze błędy1 min
  • Scenariusz praktyczny — karta produktu w e-commerce1 min
  • Audyt własnej strony Astro1 min
  • Podsumowanie1 min

Biblioteka wiedzy

Czytaj dalej

Zobacz więcej wpisów
SEO w Astro — Core Web Vitals, dane uporządkowane i techniczny fundament rankingu w 2026

SEO w Astro — Core Web Vitals, dane uporządkowane i techniczny fundament rankingu w 2026

Jak zbudować stronę w Astro, która dominuje w SEO — Core Web Vitals, sitemap, robots.txt, metadane, dane uporządkowane i GEO/AEO. Przewodnik techniczny z konkretnymi implementacjami.

Maciej Sala

Maciej Sala

Founder Strivelab

1 maja 2026
Migracja bloga z WordPress na Astro — eksport treści, przekierowania 301 i zachowanie pozycji w Google

Migracja bloga z WordPress na Astro — eksport treści, przekierowania 301 i zachowanie pozycji w Google

Kompletny przewodnik po migracji bloga z WordPress na Astro. Eksport przez REST API i WXR, mapowanie URL, przekierowania 301, migracja obrazów do astro:assets i monitoring pozycji w Google.

Maciej Sala

Maciej Sala

Founder Strivelab

1 maja 2026
Architektura wysp w Astro — czym są wyspy i dlaczego zero JS domyślnie zmienia zasady gry

Architektura wysp w Astro — czym są wyspy i dlaczego zero JS domyślnie zmienia zasady gry

Architektura wysp to fundament Astro. Wyjaśniam, czym są wyspy, jak działa selektywna hydracja, kiedy daje realną przewagę i gdzie jest jej granica — z przykładami kodu i benchmarkami.

Maciej Sala

Maciej Sala

Founder Strivelab

1 maja 2026