Askr documentation
Routing & Data

Server Queries and Preloading

Resolve query data on the server and hand it to the browser so hydration does not refetch what you already have.

Example

Register the server handler against the same query definition used by components, then prefetch into the request data runtime.

import { defineServerQueries, serveQuery } from '@askrjs/askr/data';

export const queries = defineServerQueries(
  serveQuery(projectQuery, ({ input, signal }) =>
    projects.get(input.id, { signal })
  )
);

Define server queries

serveQuery(query, handler) pairs a QueryDefinition with a ServerQueryHandler that knows how to actually fetch that query's data server-side, returning a ServerQueryEntry. defineServerQueries(...entries) collects a set of those pairings into a ServerQueryRegistry, which is what a server-side prefetch context looks handlers up against.

Register handlers

A ServerQueryHandler receives { input, request, signal } and returns the query's result, giving it access to the incoming Request when the handler needs headers, cookies, or other request context that a client-side fetch wouldn't have. The registry's get(query) method looks up the handler for a given QueryDefinition, so the same query object used on the client is the lookup key on the server.

Prefetch

createQueryPrefetchContext({ runtime, registry, request, signal, mode }) sets up a context for running queries ahead of render, with mode distinguishing 'ssr' from 'spa' prefetching. prefetchQuery(context, query, input) populates the runtime's cache, returning a boolean promise indicating whether the prefetch succeeded — but which fetch path it runs depends on mode: only 'ssr' mode looks up and calls the registered ServerQueryHandler (and skips the prefetch with a console warning if none is registered for that query); 'spa' mode never consults the registry at all and calls the query's own client-side fetch() instead.

Dehydrate and hydrate

dehydrateDataRuntime(runtime) serializes a DataRuntime's cached query data into a plain Record<string, unknown> that can be embedded in the server-rendered HTML. hydrateDataRuntime(runtime, data) does the reverse on the client, seeding a fresh runtime with that serialized data so components mounting from createQuery() find their data already cached instead of refetching on first render.