在 TanStack Router 中,預載 (Preloading) 是一種在使用者實際導航到路由之前先行載入的方式。這對於使用者接下來可能造訪的路由特別有用。舉例來說,若你有一個文章列表,而使用者很可能會點擊其中一篇文章,你可以預載該文章路由,如此當使用者點擊時就能立即顯示。
預載的路由匹配會暫時快取在記憶體中,但有幾個重要注意事項:
若你需要更多控制預載、快取或預載資料的垃圾回收,應使用外部快取函式庫如 TanStack Query。
為你的應用程式預載路由最簡單的方式是將整個路由器的 defaultPreload 選項設為 intent:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreload: 'intent',
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreload: 'intent',
})
這會預設開啟應用程式中所有 <Link> 元件的 intent 預載。你也可以在個別 <Link> 元件上設定 preload 屬性來覆寫預設行為。
預設情況下,預載會在使用者 hover 或觸碰 <Link> 元件 50ms 後開始。你可以透過設定路由器的 defaultPreloadDelay 選項來調整此延遲:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreloadDelay: 100,
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreloadDelay: 100,
})
你也可以在個別 <Link> 元件上設定 preloadDelay 屬性來針對特定連結覆寫預設行為。
若你使用內建的載入器 (loaders),可以透過設定 routerOptions.defaultPreloadStaleTime 或 routeOptions.preloadStaleTime 為毫秒數,來控制預載資料被視為新鮮的時間,直到觸發另一次預載。預設情況下,預載資料被視為新鮮的時間為 30 秒。
要變更此設定,你可以在路由器上設定 defaultPreloadStaleTime 選項:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreloadStaleTime: 10_000,
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreloadStaleTime: 10_000,
})
或者,你也可以在個別路由上使用 routeOptions.preloadStaleTime 選項:
// src/routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => fetchPost(params.postId),
// 若預載快取超過 10 秒,則再次預載路由
preloadStaleTime: 10_000,
})
// src/routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => fetchPost(params.postId),
// 若預載快取超過 10 秒,則再次預載路由
preloadStaleTime: 10_000,
})
當整合如 React Query 這類具有自有機制來判斷資料是否過時的外部快取函式庫時,你可能會想覆寫 TanStack Router 的預設預載與 stale-while-revalidate 邏輯。這些函式庫通常使用如 staleTime 等選項來控制資料的新鮮度。
要自訂 TanStack Router 的預載行為並充分運用外部函式庫的快取策略,你可以透過將 routerOptions.defaultPreloadStaleTime 或 routeOptions.preloadStaleTime 設為 0 來繞過內建快取。這確保所有預載在內部被標記為過時,且載入器總是會被呼叫,讓你的外部函式庫(如 React Query)來管理資料載入與快取。
例如:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreloadStaleTime: 0,
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
// ...
defaultPreloadStaleTime: 0,
})
這樣一來,你就能使用如 React Query 的 staleTime 選項來控制預載的新鮮度。
若你需要手動預載路由,可以使用路由器的 preloadRoute 方法。它接受一個標準的 TanStack NavigateOptions 物件,並回傳一個在路由預載完成時解析的 promise。
function Component() {
const router = useRouter()
useEffect(() => {
async function preload() {
try {
const matches = await router.preloadRoute({
to: postRoute,
params: { id: 1 },
})
} catch (err) {
// 預載路由失敗
}
}
preload()
}, [router])
return <div />
}
function Component() {
const router = useRouter()
useEffect(() => {
async function preload() {
try {
const matches = await router.preloadRoute({
to: postRoute,
params: { id: 1 },
})
} catch (err) {
// 預載路由失敗
}
}
preload()
}, [router])
return <div />
}
若你只需要預載路由的 JS chunk,可以使用路由器的 loadRouteChunk 方法。它接受一個路由物件,並回傳一個在路由 chunk 載入完成時解析的 promise。
function Component() {
const router = useRouter()
useEffect(() => {
async function preloadRouteChunks() {
try {
const postsRoute = router.routesByPath['/posts']
await Promise.all([
router.loadRouteChunk(router.routesByPath['/']),
router.loadRouteChunk(postsRoute),
router.loadRouteChunk(postsRoute.parentRoute),
])
} catch (err) {
// 預載路由 chunk 失敗
}
}
preloadRouteChunks()
}, [router])
return <div />
}
function Component() {
const router = useRouter()
useEffect(() => {
async function preloadRouteChunks() {
try {
const postsRoute = router.routesByPath['/posts']
await Promise.all([
router.loadRouteChunk(router.routesByPath['/']),
router.loadRouteChunk(postsRoute),
router.loadRouteChunk(postsRoute.parentRoute),
])
} catch (err) {
// 預載路由 chunk 失敗
}
}
preloadRouteChunks()
}, [router])
return <div />
}
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.