译零 TransZero · TanStack Query 中文文档
主站

SSR 和 SvelteKit

更新于 2026-11-02 Svelte 查看英文原文 ↗

设置

SvelteKit 默认使用服务端渲染(SSR)来渲染路由。因此,你需要在服务端禁用查询。否则,你的查询将在服务端异步持续执行,即使 HTML 已发送至客户端。

推荐的做法是在 QueryClient 对象中使用 SvelteKit 的 browser 模块。这不会禁用 queryClient.query(),而 queryClient.query() 会在下文的某个解决方案中用到。

src/routes/+layout.svelte

svelte
1<script lang="ts">2  import { browser } from '$app/environment'3  import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'4 5  let { children } = $props()6 7  const queryClient = new QueryClient({8    defaultOptions: {9      queries: {10        enabled: browser,11      },12    },13  })14</script>15 16<QueryClientProvider client={queryClient}>17  {@render children()}18</QueryClientProvider>

预取数据

Svelte Query 支持两种方式,在服务端预取数据,并通过 SvelteKit 将其传递给客户端。

若想查看理想的 SSR 设置,请参阅 SSR 示例。

使用 initialData

结合 SvelteKit 的 load,你可以将服务端加载的数据传入 createQuery 的 initialData 选项:

src/routes/+page.ts

TypeScript
1export async function load() {2  const posts = await getPosts()3  return { posts }4}

src/routes/+page.svelte

svelte
1<script lang="ts">2  import { createQuery } from '@tanstack/svelte-query'3  import type { PageProps } from './$types'4 5  let { data }: PageProps = $props()6 7  const query = createQuery(() => ({8    queryKey: ['posts'],9    queryFn: getPosts,10    initialData: data.posts,11  }))12</script>

优点:

  • 此设置极简,对某些场景而言可快速落地
  • 同时支持 +page.ts/+layout.ts 和 +page.server.ts/+layout.server.ts load 函数

缺点:

  • 若你在组件树更深层调用 createQuery,则需将 initialData 逐层向下传递
  • 若你在多个位置以相同查询调用 createQuery,则需向所有位置传递 initialData
  • 无法获知查询在服务端的确切拉取时间,因此 dataUpdatedAt 及判断查询是否需要重新拉取,均基于页面加载时间而非服务端拉取时间

使用 query

Svelte Query 支持在服务端预取查询。借助下方设置,你可在数据发送至用户浏览器前,将其拉取并注入 QueryClientProvider。因此,该数据已存在于缓存中,客户端首次渲染时无需执行初始拉取。

src/routes/+layout.ts

TypeScript
1import { browser } from '$app/environment'2import { QueryClient } from '@tanstack/svelte-query'3 4export async function load() {5  const queryClient = new QueryClient({6    defaultOptions: {7      queries: {8        enabled: browser,9        // With SSR, we usually want to set some default staleTime10        // above 0 to avoid refetching immediately on the client11        staleTime: 60 * 1000,12      },13    },14  })15 16  return { queryClient }17}

src/routes/+layout.svelte

svelte
1<script lang="ts">2  import { QueryClientProvider } from '@tanstack/svelte-query'3  import type { LayoutProps } from './$types'4 5  let { data, children }: LayoutProps = $props()6</script>7 8<QueryClientProvider client={data.queryClient}>9  {@render children()}10</QueryClientProvider>

src/routes/+page.ts

TypeScript
1import { noop } from '@tanstack/svelte-query'2 3export async function load({ parent, fetch }) {4  const { queryClient } = await parent()5 6  // You need to use the SvelteKit fetch function here7  await queryClient8    .query({9      queryKey: ['posts'],10      queryFn: async () => (await fetch('/api/posts')).json(),11    })12    .catch(noop)13}

src/routes/+page.svelte

svelte
1<script lang="ts">2  import { createQuery } from '@tanstack/svelte-query'3 4  // This data is cached by query in +page.ts so no fetch actually happens here5  const query = createQuery(() => ({6    queryKey: ['posts'],7    queryFn: async () => (await fetch('/api/posts')).json(),8  }))9</script>

优点:

  • 服务端加载的数据可在任意位置访问,无需属性透传(prop-drilling)
  • 页面渲染后,客户端不再执行初始拉取,因为查询缓存已完整保留该查询的所有信息,包括 dataUpdatedAt

缺点:

  • 初始设置需更多文件
  • 不适用于 +page.server.ts/+layout.server.ts load 函数(不过,与 TanStack Query 配合使用的 API 本身也需完全暴露给浏览器)

本页为 TanStack Query 文档(Svelte 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de