SSR & Prefetching
eden.prefetch() populates the TanStack Query cache on the server. When the client hydrates, useQuery finds the data already there — no extra fetch.
ts
await eden.prefetch(eden.proxy.users.get, queryClient)Nuxt module (recommended)
The @elysia-vue-query/nuxt module handles everything automatically — VueQueryPlugin registration, SSR dehydration, and client hydration.
bash
bun add @elysia-vue-query/nuxtts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@elysia-vue-query/nuxt'],
})That's it. No plugin file needed. The module:
- Registers
VueQueryPluginwith a freshQueryClient - Auto-imports
createEdenQueryHelpersfrom@elysia-vue-query/vue - Dehydrates query cache after SSR render (
app:renderedhook) - Hydrates query cache on client (
app:createdhook)
TIP
See the Nuxt playground for a full working example with pages, queries, and mutations.
Manual setup
If you're not using the Nuxt module (or using a different SSR framework), set up the plugin yourself:
ts
// plugins/vue-query.ts (only needed without @elysia-vue-query/nuxt)
import {
VueQueryPlugin,
QueryClient,
hydrate,
dehydrate,
} from '@tanstack/vue-query'
import type { DehydratedState } from '@tanstack/vue-query'
export default defineNuxtPlugin((nuxt) => {
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 5_000 } },
})
nuxt.vueApp.use(VueQueryPlugin, { queryClient })
if (import.meta.server) {
nuxt.hooks.hook('app:rendered', () => {
nuxt.payload['vue-query'] = dehydrate(queryClient)
})
}
if (import.meta.client) {
nuxt.hooks.hook('app:created', () => {
hydrate(queryClient, nuxt.payload['vue-query'] as DehydratedState)
})
}
})Page-level prefetch
vue
<script setup lang="ts">
import { useQueryClient } from '@tanstack/vue-query'
import { eden } from '~/lib/eden'
const queryClient = useQueryClient()
if (import.meta.server) {
await eden.prefetch(eden.proxy.users.get, queryClient)
}
const { data: users } = eden.useQuery(eden.proxy.users.get)
</script>Route middleware
ts
// middleware/prefetch-users.ts
export default defineNuxtRouteMiddleware(async () => {
if (!import.meta.server) return
const queryClient = useQueryClient()
await eden.prefetch(eden.proxy.users.get, queryClient)
})Parameterized prefetch
ts
await eden.prefetch(eden.proxy.users({ id: '1' }).get, queryClient)
await eden.prefetch(eden.proxy.users.get({ page: 1, limit: 20 }), queryClient)How hydration works
Server Client
│ │
├─ prefetch(users.get) │
├─ cache populated │
├─ dehydrate → payload │
│ │
├──── HTML + payload ──────────►│
│ ├─ hydrate(payload)
│ ├─ useQuery(users.get)
│ └─ cache hit, no fetchTanStack Query handles the serialization and hydration. elysia-vue-query just calls prefetchQuery with the right key and function.