Proč dává GraphQL na frontendu (React, Vue) smysl
GraphQL na klientovi řeší nadbytečná či chybějící data z REST API, snižuje počet zpátečních cest a přináší propracovaný model kešování a typovou bezpečnost. V kombinaci s Reactem a Vue umožňuje deklarativně popsat datové potřeby komponent, přirozeně modelovat stav načítání a chyb a efektivně spravovat klientskou mezipaměť. Klíčem je správná volba klientské knihovny, práce s fragmenty, keší a strategiemi načítání.
Architektura klienta: dotazy, mutace, fragmenty a keš
- Dotazy pro čtení dat a mutace pro změny stavu na serveru.
- Fragmenty pro znovupoužitelné výřezy schématu; ideálně kolokované s komponentami.
- Normalizovaná keš (entity adresované podle typename a primárního klíče) pro deduplikaci a okamžitou referenční konzistenci v UI.
- Politiky načítání (fetchPolicy) a aktualizační strategie pro řízení interakce keše a sítě.
Volba knihovny: Apollo Client, Relay a urql
- Apollo Client: univerzální, snadný začátek, normalizovaná keš, DevTools, rozsáhlý ekosystém (upload, persisted queries, links).
- Relay: přísná práce s fragmenty a směrováním dat, důraz na výkon a škálovatelnost, nativní stránkování pomocí kurzorů; vyšší nároky na disciplínu a build pipeline.
- urql: lehký a modulární klient s výměnnými exchanges (keš, SSR, subscriptions); dobrá volba pro menší až středně velké projekty.
Integrace s Reactem: idiomatické vzory
- Vytvořte klienta pouze jednou a zabalte aplikaci do
<ApolloProvider>nebo<Provider>(urql). - Hooks jako
useQuery,useMutation,useSubscriptionposkytují loading, error, data a refetch. - Preferujte fragmenty kolokované v souboru komponenty; sdílejte je napříč dotazy pomocí uzlů dokumentů.
- Pro komplexní seznamy využívejte field policies (Apollo) nebo connections (Relay) k řízení slučování stránkovaných výsledků.
- V Reactu 18 je lze kombinovat s Suspense a hranicemi chyb pro lepší uživatelský zážitek při načítání.
Integrace s Vue: idiomatické vzory
- Vue Apollo poskytuje
provideApolloClientauseQuery/useMutationv Composition API; pro Options API je v komponentě k dispozici objektapollo. - Reaktivní proměnné (
ref,computed) lze propojit s proměnnými dotazu (variables) a automaticky znovu načítat data. - Pro menší projekty se hodí urql-vue; zachovává koncept exchanges a jednoduchý mentální model.
Typová bezpečnost: TypeScript a generování typů
- GraphQL Code Generator převádí schéma a dokumenty na přesné typy TS a hooky pro React/Vue.
- Chraňte se před hodnotami null a schéma měňte evolučně; při změně na serveru sestavení klienta selže už v CI.
- Preferujte explicitní typy input pro mutace a úzce vymezené fragmenty pro UI.
Keš a normalizace: jak předejít opakovanému načítání a nekonzistenci
- Identifikujte entity pomocí dataIdFromObject (Apollo) či funkcí pro tvorbu klíčů; sjednoťte primární klíče v API.
- Politiky polí: definujte merge pro stránkované seznamy a strategie deduplikace.
- Optimistické aktualizace dočasně promítnou výsledek mutace do UI; následně se keš sloučí s odpovědí serveru.
- Lokální stav v keši (Apollo Reactive Vars) používejte pro jednoduché příznaky; komplexnější stav svěřte dedikovanému správci (Zustand, Redux, Pinia), ale vyvarujte se duplikování dat.
Strategie načítání: fetch policy, refetch, aktualizace na pozadí
- cache-first pro data s nízkou volatilitou; cache-and-network pro rychlé zobrazení a tichou aktualizaci.
- network-only pro kritická data, která musí být vždy aktuální; no-cache pro jednorázové dotazy, u nichž není keš potřeba.
- Refetch a pollInterval používejte střídmě; upřednostněte subscriptions nebo invalidaci keše po mutacích.
Stránkování: kurzory a Relay Connection
- Upřednostněte stránkování pomocí kurzorů před offset/limit kvůli stabilitě výsledků.
- Model Relay Connection: edges, node, pageInfo s hasNextPage/endCursor.
- V Apollu implementujte relayStylePagination pro spojování stránek v keši bez duplicit.
Aktualizace v reálném čase: subscriptions a live queries
- Přenos přes WebSocket (graphql-ws); udržujte jedno spojení na aplikaci a nastavte přiměřené časové limity a heartbeaty.
- Po přijetí události aktualizujte keš pomocí updateQuery/cache.modify nebo odpovídajících funkcí v Relay/urql.
- Alternativy: polling pro jednoduchost nebo server-sent events podle infrastruktury.
Mutace: aktualizace keše, optimistické UI a invalidace
- Pro dílčí změny použijte cache.modify nad konkrétní entitou či seznamem.
- Optimistické UI vyžaduje generování dočasných ID a pečlivé slučování; konflikty řešte návratem autoritativní odpovědi serveru.
- Při komplexních dopadech je snazší provést refetchQueries nebo invalidovat dotazy pomocí cíleného klíče.
SSR/SSG a hydratace: Next.js a Nuxt
- Při SSR předvyplňte keš na serveru a serializujte ji do HTML; klient ji převezme při hydrataci.
- Pro SSG použijte dotazy při sestavení; dynamické části načtěte na klientovi s cache-and-network.
- Dbejte na minimalizaci payloadu (odstraňte typy a ladicí pole, používejte persisted queries pro menší požadavky).
Bezpečnost a řízení přístupu na klientovi
- Tokeny ukládejte do cookies httpOnly, pokud to architektura dovoluje; jinak do paměti procesu a obnovu řešte pomocí logiky refresh.
- Autorizaci nerealizujte pouze na klientovi; klient slouží pro uživatelský komfort, rozhodnutí musí padnout na serveru či gateway.
- Omezujte frekvenci mutací spouštěných tlačítky v UI (např. pomocí debounce) a předcházejte opakovanému odesílání formulářů.
Výkon: požadavky, keš, batching a persisted queries
- Kolokované fragmenty a jejich colocation omezují over-fetching; zvažte skládání dotazů ve vrstvě BFF.
- Automatic Persisted Queries zmenšují velikost požadavků a chrání gateway před parsováním dlouhých dokumentů.
- Batching a deduplikace požadavků na klientovi zabraňují duplicitám při paralelním vykreslování.
- U velkých seznamů používejte windowing na úrovni UI a filtrování na serveru.
Nahrávání souborů a formuláře
- Pro upload využijte multipart požadavky podle standardu graphql-multipart-request-spec; Apollo Link Upload či jeho ekvivalent.
- U velkých souborů upřednostněte resumable upload přes předem podepsané URL a metadata registrujte pouze pomocí mutace.
Testování: jednotkové, integrační a kontraktační testy
- Jednotkově testujte hooky a komponenty s mockovaným klientem; využijte MockedProvider (Apollo) nebo msw pro zachytávání požadavků GraphQL.
- Kontraktační testy generujte ze schématu; změny v API musí způsobit selhání sestavení klienta.
- Storybook s mocks pro vizuální regresní testování stavu načítání, chyb a prázdných výsledků.
DevX a governance: lint, konvence a dokumentace
- Lintování dokumentů (názvy fragmentů, pojmenované operace, zákaz polí anyType) a pravidla pro importy.
- Konvence pojmenování fragmentů:
NazevKomponenty_Fragment; udržujte nejmenší potřebný výřez dat. - Generujte katalog dotazů a jejich konzumentů; usnadní to refaktoring a zastarávání polí.
Spolupráce s lokálním stavem a formuláři
- Lokální stav UI (toasty, modály) oddělte od dat ze serveru; nemíchejte je v jedné keši.
- Pro formuláře použijte knihovny s řízeným stavem (React Hook Form, VeeValidate) a validujte podle schémat (Zod/Yup).
- Optimistické mutace u formulářů doplňte o návrat do konzistentního stavu při chybě (vrácení změn v keši, hlášení chyb u polí).
Migrace z REST na GraphQL na frontendu
- Začněte po jednotlivých funkcích, ne stylem „big bang“. Vytvořte BFF/gateway, která sjednotí zdroje REST pod GraphQL.
- Postupně přepište nejproblematičtější obrazovky (s více voláními REST) a zbytek dočasně ponechte na stávajícím klientovi.
- Před migrací i po ní měřte latenci p95, počet požadavků a velikost payloadů.
Antipatterny: čemu se vyhnout
- Globální „mega-dotaz“, který poskytuje všechna data pro aplikaci; vede k obřím payloadům a obtížně udržovatelné keši.
- Duplikování stavů mezi keší GraphQL a vlastním úložištěm; stanovte jasná pravidla pro vlastnictví dat.
- Sestavování dokumentů konkatenací inline bez generování typů; snadno tak vnesete chyby do produkce.
Kontrolní seznam pro nasazení do produkce
- Generování typů TS a hooků v CI, sestavení selže při nekompatibilitě se schématem.
- DevTools zapnuté pouze ve vývojovém prostředí; ladicí link a logování v produkci vypnuté.
- Persisted queries a komprese odpovědí; správné ETag/Cache-Control pro dotazy GET ukládané v mezipaměti CDN (pokud používáte GET).
- Bezpečná správa tokenů, obnova relace a odpojování WS při nečinnosti.
- Monitorování chyb (Sentry), metrik (error rate, stale data ratio) a sledování nadbytečných vykreslení komponent (n+1).
Závěr: principy úspěšné integrace
Úspěšná integrace GraphQL s Reactem a Vue stojí na kolokaci fragmentů s komponentami, disciplinované práci s normalizovanou keší, typové bezpečnosti a promyšlených strategiích načítání. Volba knihovny by měla odpovídat velikosti týmu a nárokům projektu: Apollo pro univerzálnost, Relay pro škálování s přísnou disciplínou, urql pro jednoduchost a výkon. Díky konzistentnímu lintování, generování typů, strategiím SSR/SSG a dobře navrženému stránkování získáte rychlé UI, méně chyb a předvídatelný vývojový proces.
