SvelteKit 預設會使用伺服器渲染 (SSR) 來渲染路由。因此,你需要在伺服器端停用查詢 (query)。否則,你的查詢會繼續在伺服器端非同步執行,即使在 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>
優點:
缺點: