urql

Customizable GraphQL client for React, Vue, Svelte, Solid, and more

Library
npm
v5.0.3
8,967stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
81/100Excellent
Development Activity80
Maintenance80
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
82/100Excellent
Architecture87
Code Quality84
Innovation82
Learning Curve75

urql is a highly customizable GraphQL client built around a small, composable core (@urql/core) and framework-specific bindings for React, Vue, Svelte, Solid, Preact, and Next.js. Instead of a monolithic feature set, urql exposes behavior as a chain of “exchanges” — middleware-like units that handle caching, deduplication, fetching, retries, and more — so applications add only the capabilities they need.

Normalized caching, comparable to what heavier clients provide by default, is available as an opt-in exchange (@urql/exchange-graphcache) rather than baked into the core, keeping the base client lightweight for apps with simpler caching needs.

What You Get

  • One package (urql for React, or framework equivalents) to get a working GraphQL client in React, Preact, Vue, Solid, and Svelte
  • A composable “exchanges” pipeline for fully customizing request behavior (caching, retries, auth, persisted queries) instead of a fixed feature set
  • Optional normalized caching via @urql/exchange-graphcache for apps that need cross-query cache updates
  • Built-in document caching and request deduplication by default, without requiring the heavier normalized cache
  • Official devtools browser extension for inspecting operations, cache state, and exchange behavior

Common Use Cases

  • Adding a lightweight GraphQL client to a React, Vue, Svelte, or Solid app without pulling in a heavier client’s full feature surface
  • Building apps that need fine-grained control over caching and request behavior via custom or community exchanges
  • Adopting normalized caching incrementally by adding @urql/exchange-graphcache only once an app’s data-consistency needs grow
  • Integrating GraphQL data-fetching into meta-frameworks like Next.js via the @urql/next package’s SSR-aware exchange

Under The Hood

Architecture — The framework-agnostic engine lives in packages/core (client.ts implements the operation dispatch and subscription model, exchanges/ holds cache.ts, dedup, fetch.ts, subscription.ts, debug.ts, and ssr.ts as independent, composable middleware units chained via compose.ts). Framework packages (react-urql, vue-urql, svelte-urql, solid-urql, preact-urql, next-urql) each wrap this shared core with framework-specific hooks/composables, and @urql/exchange-graphcache plugs into the same exchange pipeline to add normalized, cross-query cache invalidation as an opt-in layer rather than a built-in default.

Tech Stack — TypeScript-first (90% of the codebase) pnpm/Turborepo-style monorepo, with a small JavaScript slice for build tooling and an HTML slice for the documentation site (packages/site). Each package publishes its own independent CHANGELOG.md and version line, coordinated via changesets.

Code Quality — The core package alone has 60+ dedicated .test.ts files across the monorepo, including snapshot tests (__snapshots__/) for exchange behavior, and each exchange (cache, fetch, subscription, debug, ssr) has its own test file colocated with its implementation. The project ships continuous, active releases (100 tagged releases, ~6 commits/month sustained since 2018) with independently versioned packages, and documents a formal v4 migration guide for breaking changes.

API Design — The exchange model is urql’s signature design decision: rather than a single opinionated cache/fetch implementation, behavior is built from small, swappable, chainable functions, letting advanced users author custom exchanges (documented explicitly in the project’s “Authoring Exchanges” guide) while default configurations stay simple for the common case. Framework bindings expose familiar idioms (React hooks, Vue composables) so the underlying exchange architecture stays invisible until a developer needs to customize it.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search