hydrejšnTakéHydrate, Client-side hydration, RehydrationPokročilý

Definice

Hydration je proces, při kterém JavaScript v prohlížeči oživí už hotové HTML vykreslené na serveru: připojí k existujícím DOM uzlům obsluhu událostí, stav a komponentový strom, aniž by značky znovu vytvářel. Uživatel díky tomu vidí obsah okamžitě, ale interaktivní se stránka stane až po stažení a spuštění klientského balíčku.

Kategorie: Webové technologieAktualizováno

Nezaměňujte: Ve frontendu hydration znamená oživení serverem vykresleného HTML JavaScriptem, zatímco v ORM a datových vrstvách označuje naplnění objektu hodnotami z databázového záznamu.

Proč hydration vůbec vznikla

Hydration je důsledek toho, že server-side rendering a klientské frameworky řeší dvě různé potřeby. Server umí poslat hotové HTML, takže uživatel i vyhledávač vidí obsah v první odpovědi. Klientský framework ale potřebuje vlastní strom komponent, stav a posluchače událostí, aby tlačítka reagovala. Hydration je most mezi obojím: framework projde doručený DOM, spáruje ho se svým stromem a doplní chybějící chování. Podrobněji o samotném vykreslování viz Render.

Co se v prohlížeči odehraje

Průběh hydration má pevné pořadí. Prohlížeč nejdřív vykreslí HTML a uživatel vidí obsah. Potom stáhne JavaScriptový balíček, spustí ho a framework znovu odsimuluje první render komponent. Výsledek porovná s existujícími uzly: pokud sedí, jen k nim připojí handlery a inicializuje stav. Data, která server použil při renderu, se obvykle přenášejí serializovaná v HTML, aby klient nemusel volat API znovu.

Uncanny valley mezi zobrazením a interaktivitou

Mezi vykreslením HTML a dokončením hydration existuje okno, kdy stránka vypadá hotově, ale kliknutí nic neudělá. Delší balíček znamená delší okno. Metriky jako Interaction to Next Paint tuhle mezeru odhalují, i když First Contentful Paint vypadá skvěle.

Hydration mismatch

Pokud se klientský render liší od serverového, framework hlásí mismatch. Typické příčiny jsou Date.now(), náhodná čísla, čtení window nebo localStorage během renderu a HTML neplatné podle parseru (například <div> uvnitř <p>). React v takovém případě podstrom raději zahodí a vykreslí ho od nuly, což stojí výkon a může zablikat.

Jak se náklady hydration snižují

  • Partial hydration: oživí se jen vybrané komponenty, zbytek zůstane statickým HTML.
  • Islands architecture: stránka je převážně statická a interaktivní ostrůvky se hydratují nezávisle, každý s vlastním malým balíčkem.
  • Selective a progressive hydration: React Server Components a streamovaný Suspense hydratují podstromy postupně, podle toho, jak dorazí jejich data.
  • Resumability: přístup, který hydration nahrazuje serializací stavu do HTML, takže klient nemusí první render opakovat. Používá ho Qwik.
  • Žádný JavaScript: u čistě obsahových stránek je nejlevnější hydration ta, která se nekoná.

Kde se termín používá jinak

Slovo hydration se objevuje i mimo frontend. V ORM a datových vrstvách znamená naplnění objektu hodnotami z databázového řádku, tedy převod plochých dat na doménovou entitu. Kontext obvykle rozliší význam spolehlivě, ale v mixed týmech se vyplatí říct, o kterou hydration jde.

Příklady z praxe

  1. React: hydrateRoot místo createRoot

    Aplikace vykreslená na serveru se v prohlížeči nesmí nabootovat přes createRoot, protože ten by existující HTML zahodil a vykreslil znovu. Správný vstupní bod je hydrateRoot, který se naváže na už doručené uzly. Pokud se stromy neshodnou, React ohlásí chybu a problematický podstrom přerenderuje.

    import { hydrateRoot } from 'react-dom/client';
    import App from './App';
    
    // #root už obsahuje HTML ze serveru
    hydrateRoot(document.getElementById('root'), <App />);
  2. Mismatch kvůli času vykreslení

    Komponenta zobrazující aktuální čas vygeneruje na serveru jinou hodnotu než o vteřinu později v prohlížeči, takže vznikne hydration mismatch. Řešením je vykreslit na serveru neutrální obsah a skutečný čas doplnit až v efektu po hydration, případně formátovat na klientovi s pevným časovým pásmem.

    function Clock() {
      const [time, setTime] = useState(null);
      useEffect(() => setTime(new Date()), []);
      return <span>{time ? time.toLocaleTimeString() : '--:--:--'}</span>;
    }

Časté omyly

MýtusKdyž je stránka vykreslená na serveru, je hned interaktivní.
Ve skutečnostiServerové HTML dá jen vzhled a obsah. Tlačítka, formuláře a routing začnou fungovat až po stažení a spuštění klientského balíčku a dokončení hydration, což u velkých aplikací trvá stovky milisekund i sekundy.
MýtusHydration mismatch je jen varování v konzoli, které se dá ignorovat.
Ve skutečnostiMismatch znamená, že framework nemůže existující DOM použít a podstrom vykreslí znovu. Ztrácí se tím výhoda SSR, může zmizet stav vloženého obsahu a uživatel vidí probliknutí.
MýtusHydration se dá zrychlit tím, že se HTML pošle menší.
Ve skutečnostiDobu hydration určuje především velikost a náročnost JavaScriptu, ne velikost HTML. Zkrácení se dosahuje menším balíčkem, partial hydration nebo úplným odstraněním JS u statických částí stránky.

Časté dotazy

Jak poznám, že hydration zpomaluje moji stránku?
Zpomalení kvůli hydration se pozná z rozdílu mezi metrikami zobrazení a interaktivity. Když First Contentful Paint vychází dobře, ale Interaction to Next Paint nebo Total Blocking Time jsou vysoké, stránka se ukáže rychle a jen dlouho nereaguje. V profileru prohlížeče se to projeví jako souvislý blok práce v hlavním vlákně krátce po načtení skriptu. Pomůže zmenšit balíček, odložit nekritické komponenty přes dynamický import a nechat statické části stránky bez JavaScriptu.
Jak opravit hydration mismatch v Reactu nebo Next.js?
Hydration mismatch se opravuje odstraněním všeho, co se mezi serverem a klientem liší. Nejčastěji jde o aktuální čas, náhodná čísla, přístup k window, localStorage nebo cookies během renderu, jinou lokalizaci a rozšíření prohlížeče, která mění DOM. Řešení je vykreslit na serveru deterministický obsah a klientskou hodnotu doplnit až v useEffect, případně komponentu načíst dynamicky bez SSR. Zkontrolujte také validitu HTML: zanořený odstavec nebo blokový prvek uvnitř inline prvku parser opraví a stromy pak nesedí.
Potřebuje každá stránka hydration?
Hydration potřebují jen stránky s klientskou interaktivitou. Blogový článek, dokumentace nebo landing page bez formulářů a stavu se obejde čistým HTML a CSS, případně několika řádky vanilla JavaScriptu. Frameworky jako Astro nebo Eleventy z toho dělají výchozí režim a interaktivní části řeší jako izolované ostrůvky. Nasazení plného SPA frameworku na statický obsah znamená posílat balíček, který uživateli nic nepřidá, a přesto blokuje hlavní vlákno.
Co znamená resumability oproti hydration?
Resumability je alternativa k hydration, která se snaží úplně vynechat opakování prvního renderu na klientovi. Stav aplikace i informace o tom, který posluchač patří ke kterému prvku, se serializují přímo do HTML. Prohlížeč pak po kliknutí načte jen ten kousek kódu, který danou událost obsluhuje. Tenhle přístup prosazuje framework Qwik. Cenou je složitější serializace, větší HTML a menší ekosystém než u zavedených řešení s hydration.

Zdroje

  1. hydrateRoot(otevře se v novém okně)React
  2. Rendering(otevře se v novém okně)Vercel
  3. HTML Standard(otevře se v novém okně)WHATWG
  4. Document Object Model (DOM)(otevře se v novém okně)MDN Web Docs

Související pojmy

Potřebujete to vyřešit v praxi?

Poradíme, jak na to ve vašem projektu

Vysvětlit pojem je jedna věc, navrhnout kolem něj funkční řešení druhá. Ozvěte se a probereme, co dává smysl u vás.