SvelteKit 默认使用服务端渲染 (SSR) 来渲染路由。因此,您需要在服务端禁用查询功能。否则,即使在 HTML 已发送至客户端后,您的查询仍会在服务端继续异步执行。
推荐的方式是在 QueryClient 对象中使用 SvelteKit 的 browser 模块。这不会禁用 queryClient.prefetchQuery(),该方法会在以下解决方案之一中使用。
src/routes/+layout.svelte
<script lang="ts">
import { browser } from '$app/environment'
import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
enabled: browser,
},
},
})
</script>
<QueryClientProvider client={queryClient}>
<slot />
</QueryClientProvider>
<script lang="ts">
import { browser } from '$app/environment'
import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
enabled: browser,
},
},
})
</script>
<QueryClientProvider client={queryClient}>
<slot />
</QueryClientProvider>
Svelte Query 支持两种在服务端预取数据并通过 SvelteKit 传递至客户端的方式。
如需查看理想的 SSR 配置,请参考 SSR 示例。
结合 SvelteKit 的 load 方法,您可以将服务端加载的数据传入 createQuery 的 initialData 选项:
src/routes/+page.ts
export async function load() {
const posts = await getPosts()
return { posts }
}
export async function load() {
const posts = await getPosts()
return { posts }
}
src/routes/+page.svelte
<script>
import { createQuery } from '@tanstack/svelte-query'
import type { PageData } from './$types'
export let data: PageData
const query = createQuery({
queryKey: ['posts'],
queryFn: getPosts,
initialData: data.posts,
})
</script>
<script>
import { createQuery } from '@tanstack/svelte-query'
import type { PageData } from './$types'
export let data: PageData
const query = createQuery({
queryKey: ['posts'],
queryFn: getPosts,
initialData: data.posts,
})
</script>
优点:
缺点:
Svelte Query 支持在服务端预取查询。通过以下配置,您可以在数据发送至用户浏览器前将其预取并传入 QueryClientProvider。因此,数据已存在于缓存中,客户端不会发生初始获取。
src/routes/+layout.ts
import { browser } from '$app/environment'
import { QueryClient } from '@tanstack/svelte-query'
export async function load() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
enabled: browser,
},
},
})
return { queryClient }
}
import { browser } from '$app/environment'
import { QueryClient } from '@tanstack/svelte-query'
export async function load() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
enabled: browser,
},
},
})
return { queryClient }
}
src/routes/+layout.svelte
<script lang="ts">
import { QueryClientProvider } from '@tanstack/svelte-query'
import type { LayoutData } from './$types'
export let data: LayoutData
</script>
<QueryClientProvider client={data.queryClient}>
<slot />
</QueryClientProvider>
<script lang="ts">
import { QueryClientProvider } from '@tanstack/svelte-query'
import type { LayoutData } from './$types'
export let data: LayoutData
</script>
<QueryClientProvider client={data.queryClient}>
<slot />
</QueryClientProvider>
src/routes/+page.ts
export async function load({ parent, fetch }) {
const { queryClient } = await parent()
// 此处需使用 SvelteKit 的 fetch 函数
await queryClient.prefetchQuery({
queryKey: ['posts'],
queryFn: async () => (await fetch('/api/posts')).json(),
})
}
export async function load({ parent, fetch }) {
const { queryClient } = await parent()
// 此处需使用 SvelteKit 的 fetch 函数
await queryClient.prefetchQuery({
queryKey: ['posts'],
queryFn: async () => (await fetch('/api/posts')).json(),
})
}
src/routes/+page.svelte
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
// 此数据已被 +page.ts 中的 prefetchQuery 缓存,因此此处不会实际发起请求
const query = createQuery({
queryKey: ['posts'],
queryFn: async () => (await fetch('/api/posts')).json(),
})
</script>
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
// 此数据已被 +page.ts 中的 prefetchQuery 缓存,因此此处不会实际发起请求
const query = createQuery({
queryKey: ['posts'],
queryFn: async () => (await fetch('/api/posts')).json(),
})
</script>
优点:
缺点: