Learning
Všechny články
Frontend14. září 2026 6 min

Waterfall nevzniká na síti, vzniká ve stromu

Když request potřebuje render rodiče, pořadí požadavků kopíruje hierarchii

Kdo si říká o data až při renderu, čeká na svého rodiče

Network waterfall se obvykle diagnostikuje jako problém výkonu backendu nebo latence. Skoro nikdy jím není. Je to strukturální jev a jeho příčina je v tom, kdy se požadavek vůbec dozví, že má vzniknout.

Když komponenta fetchuje ve svém efektu, request se odešle až poté, co se komponenta vykreslila. Aby se vykreslila, musel se vykreslit rodič. A pokud rodič čekal na vlastní data, dítě se dostane ke slovu až po jeho okružní cestě. Hloubka stromu se tím převede na počet sériových round tripů.


Race condition je stejná vada, jen viditelnější

Než dojde na topologii, narazíš na bližší důsledek téhož mechanismu. Requesty vznikají nezávisle a jejich odpovědi nemají zaručené pořadí.

Když rychle napíšeš „hello“, query projde hodnotami h, he, hel, hell a hello. To rozjede pět fetchů a odpověď na hell může dorazit až po odpovědi na hello. Protože zavolá setResults() jako poslední, na obrazovce zůstanou výsledky pro nesprávný dotaz.

Standardní obrana je úklidová funkce s příznakem:

useEffect(() => {
  let ignore = false;
  fetchResults(query, page).then(json => {
    if (!ignore) {
      setResults(json);
    }
  });
  return () => {
    ignore = true;
  };
}, [query, page]);

Tím se zahodí všechny odpovědi kromě té poslední vyžádané. Stojí za povšimnutí, že odpovědi nezruší, jen je ignoruje. Práce na serveru proběhla, přenos proběhl, jen se výsledek vyhodí.


Seznam věcí, které fetch v efektu neřeší

Dokumentace je v tomhle nezvykle přímá a vyjmenovává, co zbývá vyřešit i po správném ošetření race condition. Cachování odpovědí, aby uživatel po kliknutí zpět viděl předchozí obrazovku okamžitě. Načítání dat na serveru, aby úvodní HTML obsahovalo data místo spinneru. A vyhýbání se network waterfallům, aby dítě mohlo fetchovat, aniž by čekalo na každého rodiče.

Tyhle tři problémy spolu souvisí víc, než je zjevné. Všechny tři plynou z jednoho rozhodnutí: že se o datech rozhoduje až při renderu komponenty, která je potřebuje. Kolokace požadavku ke komponentě je z hlediska čitelnosti kódu skvělá, ale sama o sobě určuje i pořadí a načasování.

Řešení proto nespočívá ve vypnutí kolokace. Spočívá v oddělení dvou věcí, které efekt slepuje dohromady: co komponenta potřebuje, a kdy se to začne načítat. Framework, který statické závislosti dat zná dřív než render, umí požadavky spustit paralelně nebo je poslat na server v jednom průchodu, a přitom deklaraci nechat u komponenty.


Co si z toho odnést

Když ve waterfall diagramu vidíš schody, nehledej pomalý endpoint. Spočítej, kolik schodů odpovídá úrovním tvého komponentového stromu. Když ta čísla sedí, není to problém sítě a zrychlení backendu ti ho neopraví, jen zkrátí každý schod.

Z toho plyne konkrétní postup. Zvedni požadavek na data nahoru nad bod, kde vzniká závislost, aby se sourozenci načítali souběžně, nebo použij mechanismus, který závislosti zná předem: loadery na úrovni routy, dotazy vyhlášené při definici routy, nebo Server Components, kde se celý strom zpracuje na serveru a klient dostane výsledek streamem.

A pokud fetch v efektu zůstat musí, minimálně ho schovej do vlastního hooku typu useData(). Nevyřeší to cachování ani waterfall, ale soustředí to na jedno místo, takže výměna za lepší mechanismus bude později změna v jednom souboru, ne v padesáti komponentách.

Zdroje

Poslech místo čtení — 2 zdroje k načtení.