/graphql-playground

GraphQL client query caching and invalidation playground

Primary LanguageTypeScript

graphql-playground

GraphQL client data fetching and caching playground.

Each demo consists of 3 components:

  1. <Numbers> consists of an input field which expects a comma separated list of numbers that are saved on blur; mutation SaveNumbers
  2. <First> that fetches the first number saved; query GetNumber
  3. <Sum> that fetches the sum of the numbers; query GetSum

Apollo Client

⭐ 18k

  • allows for direct cache manipulation (limited API)
  • refetchQueries only works on watched queries (= queries in rendered components)
  • there are libraries out there to manage cache updates, but they are hacky

Apollo Client with IsLatestLink & useLatestQuery

✅ addon on top of what we have

🔶 hacky

Constraints

  1. A query should not skip cache unless explicitly told to do so
  • Example: query Q ignores LatestLink before mutation M ran
  • Example: query Q uses cache, mutation M modifies state, query Q skips cache
  1. A unique query has to be marked as having the latest data
  • Example: query Q1 uses cache under key K, query Q2 with key K skips cache
  1. Don't grow the internal map too large
  • Example: orphaned queries that never get cleared

NerdWallet ApolloCachePolicies

⭐ 121

✅ addon on top of what we have (InMemoryCache)

🔶 how much maintenance will this have? what are its bugs?

  • invalidation policies introduce event-based (onWrite, onEvict) policies between parent/child type entities.
  • type TTL which would replace our useTtlQuery

urql

⭐ 8k

✅ easier to migrate to with a better cache API

🔶 we will have to write our own cache invalidation as part of an "Exchange" which won't live with the query/mutation itself

  • same(ish) API and approach as Apollo
  • cache management (by default is a document cache but we'd want to use a normalized cache) is handled via an "Exchange" which might be easier to extend upon as they cover both caching and what Apollo calls "Links" (= network requests)
    • cache.invalidate lets us essentialy walk and discard any cache fields
    • writing of the mutation updates and query links can be made easier using schema awareness

React Query née TanStack Query

⭐ 31k

✅ most powerful cache (and beyond) control, highly composable/extensible

🔶 most difficult to migrate to

  • can pass invalidateQueries which can invalidate a query that starts with a key (without immediately re-excuting it unless it's being currently rendered by useQuery)
    • the key prefixes/matchers are powerful
  • supports time-based cache expiry meaning it could replace our useTtlQuery
  • does NOT come with a data fetching library out of the box (= backend agnostic)
  • supports optimistic updates
  • there is an (experimental) broadcastQueryClient that shares state across multiple browser tabs

SWR

⭐ 25k

🔶 Might as well use React Query with a better API. Discourages direct cache writes and doesn't provide any utils to generate keys etc.