Proč GraphQL na frontendu (React, Vue) dává smysl
GraphQL na klientovi řeší nadbytečná či chybějící data z REST API, snižuje počet round-tripů a přináší robustní 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 strategií načítání.
Architektura klienta: dotazy, mutace, fragmenty a keš
- Dotazy slouží ke čtení dat a mutace ke změnám stavu na serveru.
- Fragmenty umožňují znovupoužitelné části schématu; ideálně by měly být ko-lokovány s komponentami.
- Normalizovaná keš (entity adresované dle typename a primárního klíče) umožňuje deduplikaci a okamžitou referenční konzistenci v uživatelském rozhraní.
- Politiky načítání (fetchPolicy) a strategie aktualizací řídí interakci mezi keší a sítí.
Volba knihovny: Apollo Client, Relay a urql
- Apollo Client: univerzální řešení se snadným začátkem, normalizovanou keší, nástroji DevTools a rozsáhlým ekosystémem (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í kurzorové stránkování; vyžaduje vyšší disciplínu a specializovanou build pipeline.
- urql: lehký a modulární klient s výměnnými exchanges (keš, SSR, subscriptions); vhodný zejména pro menší až střední projekty.
Integrace s Reactem: idiomatické vzory
- Vytvořte jednorázový klient a zabalte aplikaci do
<ApolloProvider>nebo<Provider>(urql). - Hooks jako
useQuery,useMutation,useSubscriptionposkytují stav loading, error, data a možnost refetch. - Preferujte fragmenty ko-lokované v souboru komponenty; sdílejte je mezi dotazy pomocí dokumentových uzlů.
- Pro komplexní seznamy využívejte field policies (Apollo) nebo connections (Relay) k řízení slučování stránkovaných výsledků.
- Při použití React 18 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 k dispoziciapolloobjekt v komponentě. - Reaktivní proměnné (
ref,computed) lze navázat na proměnné dotazu (variables) a automaticky v nich provádět refetch. - Pro menší projekty je praktické použít 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é TS typy a React/Vue hooky.
- Chraňte se před problémem nullability a provádějte evoluční změny schématu; při změně serveru build klienta selže již v CI.
- Preferujte explicitní input typy pro mutace a úzce vymezené fragmenty pro uživatelské rozhraní.
Keš a normalizace: jak předejít přenačítání a nekonzistenci
- Identifikace entit pomocí dataIdFromObject (Apollo) nebo klíčovacích funkcí; sjednoťte primární klíče v API.
- Politiky polí: definujte merge funkce pro stránkované seznamy a strategie deduplikace.
- Optimistické aktualizace dočasně promítnou výsledek mutace do UI; následně se keš synchronizuje s odpovědí serveru.
- Lokální stav v keši (Apollo Reactive Vars) slouží pro jednoduché příznaky; komplexnější stav svěřte dedikovanému správci (Zustand, Redux, Pinia), ale vyhněte se duplikaci dat.
Strategie načítání: fetch policy, refetch, background refresh
- cache-first je vhodná pro data s nízkou dynamikou; cache-and-network umožňuje rychlé zobrazení s tichou aktualizací na pozadí.
- network-only volte u kritických dat, která musí být vždy aktuální; no-cache pro jednorázové dotazy, které nepotřebují keš.
- Refetch a pollInterval používejte střídmě; preferujte subscriptions nebo invalidaci keše po mutacích.
Stránkování: kurzory a Relay Connection
- Preferujte kurzorové stránkování před offset/limit kvůli stabilitě a předvídatelnosti výsledků.
- Relay Connection model používá strukturu edges, node, pageInfo s indikátory hasNextPage a endCursor.
- V Apollo Clientu implementujte relayStylePagination pro správné slučování načítaných stránek v keši bez duplicit.
Aktualizace v reálném čase: subscriptions a live queries
- Transport přes WebSocket (graphql-ws); udržujte jedno připojení na aplikaci, nastavte rozumné časové limity a heartbeaty.
- Po příchodu události aktualizujte keš pomocí updateQuery/cache.modify nebo ekvivalentních funkcí v Relay či urql.
- Alternativně lze použít polling pro jednoduchá řešení nebo server-sent events, podle schopností infrastruktury.
Mutace: aktualizace keše, optimistic UI a invalidace
- Pro jemné změny využívejte cache.modify cíleně na entitu či seznam.
- Optimistické UI vyžaduje generování dočasných ID a pečlivé slévání výsledků; konflikty řešte návratem autoritativní odpovědi ze serveru.
- Při komplexních dopadech je jednodušší provést refetchQueries nebo cíleně invalidovat dotazy pomocí klíčů.
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ři hydrataci převezme.
- Pro SSG využijte build-time dotazy; dynamické části dočtěte na klientu s politikou cache-and-network.
- Dbejte na minimalizaci payloadu (odstraňování typů a debug polí, persisted queries pro menší dotazy).
Bezpečnost a řízení přístupu na klientovi
- Tokeny ukládejte do httpOnly cookies, je-li to možné v architektuře; jinak jen do paměti procesu a obalujte automatickou obnovou refreshe.
- Autorizaci nikdy neprovádějte pouze na klientovi; klient je určen pro UX, rozhodnutí musí provádět server či gateway.
- Omezte frekvenci mutací přes UI (např. debounce) a bráníte opakovaným odesláním formulářů.
Výkon: požadavky, keš, batching a persisted queries
- Co-lokované fragmenty a colocation omezují over-fetching; zvažte skládání dotazů v BFF vrstvě.
- Automatic Persisted Queries snižují velikost požadavků a odlehčují gateway od parsování rozsáhlých dokumentů.
- Batching a deduplikace požadavků na klientském straně brání duplicitám při paralelním renderování.
- Pro velké seznamy používejte windowing na úrovni UI a serverové filtrování.
Nahrávání souborů a formuláře
- Pro upload využijte multipart requesty dle standardu graphql-multipart-request-spec s nástroji jako Apollo Link Upload či ekvivalentem.
- Při velkých souborech preferujte resumable upload přes předpodepsané URL a mutací pouze registrujte metadata.
Testování: jednotkové, integrační a kontraktační testy
- Jednotkově testujte hooky a komponenty s mockovaným klientem; použijte MockedProvider (Apollo) nebo msw pro intercept GraphQL požadavků.
- Kontraktační testy generujte ze schématu; změny v API musí vyvolat neúspěšný build klienta.
- Storybook využívejte s mocks pro vizuální regresní testování stavů načítání, chyb a prázdných výsledků.
DevX a governance: lint, konvence a dokumentace
- Lintování GraphQL dokumentů (názvy fragmentů, pojmenované operace, zákaz anyType polí) a pravidla pro importy.
- Konvence pro názvy fragmentů:
NazevKomponenty_Fragment; udržujte nejmenší možný výřez dat. - Generujte katalog dotazů a jejich konzumentů; zjednodušuje to refactoring a odstraňování nepoužívaných polí.
Spolupráce s lokálním stavem a formuláři
- Lokální UI stav (notifikace, modály) oddělte od dat ze serveru; nemíchejte je ve stejné keši.
- Pro formuláře používejte knihovny s řízeným stavem (React Hook Form, VeeValidate) a validujte je podle schémat (Zod, Yup).
- Optimistické mutace u formulářů doplňte o návrat do konzistentního stavu při chybě (rollback keše, hlášení chyb na pole).
Migrace z REST na GraphQL na frontendu
- Začněte po funkcích, ne „big bang“ přechodem. Vytvořte BFF/gateway, která sjednotí REST zdroje pod GraphQL rozhraní.
- Postupně přepište nejvíce problematické obrazovky (více REST volání) a zbytek nechte dočasně na stávajícím klientovi.
- Měřte 95. percentil latence, počet požadavků a velikost přenášených dat před a po migraci.
Antipatterny: čemu se vyhnout
- Globální „mega-dotaz“ poskytující všechna data pro aplikaci; vede k obří velikosti payloadů a těžko udržitelné keši.
- Duplikace stavů mezi GraphQL keší a vlastním storem; zvolte jasná pravidla vlastnictví dat.
- Inline slučování dokumentů bez generování typů; snadno zavlečete chyby do produkce.
Checklist pro produkční nasazení
- Generování TS typů a hooků v CI s neúspěšným buildem při nekompatibilitě schématu.
- DevTools aktivní pouze v developmentu; v produkci vypněte debug link a logování.
- Persisted queries a komprese odpovědí; správné využití ETag a Cache-Control pro CDN-cacheované GET dotazy (pokud používáte GET).
- Bezpečná správa tokenů, obnova relace a ukončování WS spojení při nečinnosti.
- Monitorování chyb (Sentry), metrik (error rate, stale data ratio) a sledování nadbytečných renderů UI komponent.
Závěr: principy úspěšné integrace
Úspěšná integrace GraphQL s Reactem a Vue stojí na ko-lokaci 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 požadavkům projektu: Apollo pro univerzálnost, Relay pro škálování s přísnou disciplínou a urql pro jednoduchost a výkon. Díky konzistentnímu lintování, generování typů, SSR/SSG strategiím a dobře navrženému stránkování získáte rychlé uživatelské rozhraní, méně chyb a předvídatelný vývojový proces.