One request per render, streamed back field by field.
laguz batches the GraphQL queries your React components declare into a single request per commit. With its server package, each field comes back the moment it resolves, and queries that depend on each other share the same round trip.
npm install @laguzjs/client
When each widget gets its data
How it works
Components ask for what they need
Each component selects its own fields with a hook, as it would with any data library. It receives exactly that selection, under its own names.
function Header() {
const { data } = useData(pool, "user", { id: 1 },
["name", { avatar: { args: { size: 32 } } }]);
return <h1>{data?.name}</h1>;
}
One commit becomes one query
Everything a render asks for goes out together. Selections on the same field are merged, fields already cached or in flight are skipped, and arguments can point at another field's result.
{
q0: user(id: 1) {
name teamId avatar_ccrvkh: avatar(size: 32)
}
q1: team(id: $_ref__q0__teamId) { leadId }
q2: stats { revenue }
}
Fields flow back as they resolve
@laguzjs/server runs every root field on its own and writes a line as
soon as one is done. Fast widgets render right away, a slow query only delays
itself, and an invalid field fails alone.
{"data":{"q0":{"name":"Ada Lovelace", …}}}
{"data":{"q1":{"leadId":"3"}}}
… 300 ms later
{"data":{"q2":{"revenue":48210.5}}}
Measured against TanStack Query
Same components, same server, headless Chromium, HTTP/2 with brotli on a slow 4G link. Medians of five runs.
| Scenario | TanStack Query | laguz |
|---|---|---|
| 20-widget page, median widget on screen | 278 ms, 20 requests | 171 ms, 1 request |
| Database round trips for that page | 28 | 6 |
| Response bytes for that page | 2.2 KB | 0.9 KB |
| Refresh an infinite list with 5 pages | 832 ms, 5 requests | 171 ms, 1 request |
| Three dependent queries | 498 ms, 3 requests | 186 ms, 1 request |
On a fast network over HTTP/2 the latencies are close, and what remains is fewer requests and less work for the server. Methodology and full results.
Get started
In the browser
import { createPool, httpFetcher } from "@laguzjs/client";
import { useData } from "@laguzjs/client/react";
const pool = createPool(
httpFetcher("/graphql", { stream: true }),
);
On the server
import { batchLoader, createHandler } from "@laguzjs/server";
export const POST = createHandler({
schema,
context: () => ({ users: batchLoader(loadUsers) }),
});