preload.ts
Overview
The preload.ts file is a utility module within the SWR (stale-while-revalidate) data fetching ecosystem that enables data preloading. Its main purpose is to allow data fetching operations to be initiated before a React component mounts and requests that data, thereby reducing loading delays and avoiding redundant network requests.
This module provides:
A
preloadfunction that accepts a cache key and a fetcher function, invoking the fetcher and caching the resulting Promise in a dedicated preload cache.A middleware function that integrates with SWR hooks (
useSWR) to transparently consume preloaded data, returning the cached Promise if available, and deleting it after consumption to prevent reuse.
Together, they enable anticipatory data fetching with seamless integration into the SWR lifecycle, improving perceived performance and reducing fetch duplication.
Detailed Explanation
Type Definitions
type PreloadFetcher<
Data = unknown,
SWRKey extends Key = Key
> = SWRKey extends () => infer Arg
? (arg: Arg) => FetcherResponse<Data>
: SWRKey extends infer Arg
? (arg: Arg) => FetcherResponse<Data>
: never
Purpose: Defines the type for fetcher functions used in preloading.
If the
SWRKeyis a function, it extracts its argument type and defines a fetcher that takes that argument.Otherwise, the fetcher takes the
SWRKeytype itself as an argument.Returns a
FetcherResponse<Data>(usually a Promise or synchronous data).
preload Function
export const preload = <
Data = any,
SWRKey extends Key = Key,
Fetcher extends BareFetcher = PreloadFetcher<Data, SWRKey>
>(
key_: SWRKey,
fetcher: Fetcher
): ReturnType<Fetcher> => {
const [key, fnArg] = serialize(key_)
const [, , , PRELOAD] = SWRGlobalState.get(cache) as GlobalState
// Prevent preload to be called multiple times before used.
if (PRELOAD[key]) return PRELOAD[key]
const req = fetcher(fnArg) as ReturnType<Fetcher>
PRELOAD[key] = req
return req
}
Purpose
Initiates a fetch operation ahead of time and caches the resulting request Promise in a dedicated preload cache.
Ensures idempotency by returning the cached Promise if a preload for the same key is already in progress.
Parameters
key_(SWRKey): The key identifying the resource to fetch. Can be a primitive, array, or function returning an argument.fetcher(Fetcher): The fetcher function that accepts the deserialized key argument and returns a fetch Promise or data.
Returns
The return value of the fetcher function, typically a
Promise<Data>.
Usage Example
import { preload } from './preload'
const key = ['user', 123]
const fetcher = (id: number) => fetch(`/api/user/${id}`).then(res => res.json())
// Initiate preload
const preloadPromise = preload(key, fetcher)
// Later, when component mounts, useSWR with the same key will consume this preloaded data
Implementation Details
Calls
serializeto convert the key into a stable string key and extract the argument for the fetcher.Accesses the global
PRELOADcache fromSWRGlobalState.Checks if a preload Promise for the key already exists; if so, returns it immediately.
Otherwise, invokes the fetcher with the serialized argument, stores the returned Promise in
PRELOAD, and returns it.
middleware Function
export const middleware: Middleware =
useSWRNext => (key_, fetcher_, config) => {
// fetcher might be a sync function, so this should not be an async function
const fetcher =
fetcher_ &&
((...args: any[]) => {
const [key] = serialize(key_)
const [, , , PRELOAD] = SWRGlobalState.get(cache) as GlobalState
if (key.startsWith(INFINITE_PREFIX)) {
// we want the infinite fetcher to be called.
// handling of the PRELOAD cache happens there.
return fetcher_(...args)
}
const req = PRELOAD[key]
if (isUndefined(req)) return fetcher_(...args)
delete PRELOAD[key]
return req
})
return useSWRNext(key_, fetcher, config)
}
Purpose
Acts as SWR middleware to intercept fetch calls inside
useSWR.Checks for preloaded data in the
PRELOADcache and returns it if available, preventing duplicate fetches.Deletes the preload entry on consumption to avoid stale reuse.
Bypasses keys prefixed for infinite loading, delegating handling to infinite loading mechanisms.
Parameters
useSWRNext: The next SWR hook or middleware function in the chain.Returns a function that takes:
key_: The SWR key.fetcher_: The original fetcher function.config: SWR configuration.
Returns
The result of
useSWRNextcalled with the wrapped fetcher.
Usage Example
import useSWR from 'swr'
import { middleware as preloadMiddleware } from './preload'
const useSWRWithPreload = (key, fetcher, config) =>
useSWR(key, fetcher, { ...config, middleware: [preloadMiddleware] })
const Component = () => {
const { data, error } = useSWRWithPreload('user:123', fetchUser)
// If data was preloaded, fetchUser won't be called again here.
}
Implementation Details
Serializes the key to a string.
Retrieves the global preload cache.
If the key starts with
INFINITE_PREFIX, calls the fetcher directly (no preload).If a preload Promise exists for the key, deletes it from the cache and returns it.
Otherwise, calls the original fetcher.
Important Implementation Details and Algorithms
Key Serialization:
Uses theserializeutility to transform complex keys (arrays, functions) into stable string keys ensuring consistent cache access.Idempotent Preloading:
Thepreloadfunction prevents multiple fetches for the same key by returning the cached Promise if it exists.Cache Separation:
Maintains a dedicated preload cache (PRELOAD) within the global SWR state separate from the data cache to track prefetch Promises.Consumption and Cleanup:
The middleware deletes the preload cache entry upon first consumption, preventing reuse or stale data serving.Infinite Loading Bypass:
Keys with theINFINITE_PREFIXare skipped by the preload middleware to avoid conflicts with infinite loading's own caching and fetching logic.
Interaction with Other Parts of the System
useSWRHook:
The middleware integrates withuseSWRto transparently supply preloaded data, avoiding duplicate fetches and allowing components to render immediately with cached data.Global Cache and State (
SWRGlobalStateandcache):
The preload cache is stored inside global SWR state allowing coordination between preloading and fetch consumption.serializeUtility:
Ensures consistent and unique string keys for caching and lookup.Infinite Loading (
useSWRInfinite):
The middleware explicitly excludes infinite loading keys from preload logic, deferring to infinite loading's specialized handling.
Mermaid Diagram: Class & Function Structure
flowchart TD
A[preload(key, fetcher)] -->|serialize key| B[Check PRELOAD cache]
B -->|exists| C[Return cached Promise]
B -->|not exists| D[Call fetcher with argument]
D --> E[Store Promise in PRELOAD cache]
E --> F[Return Promise]
subgraph SWR Middleware Flow
G[useSWR calls fetcher(key_)] --> H[serialize key_]
H --> I{Key starts with INFINITE_PREFIX?}
I -- Yes --> J[Call original fetcher]
I -- No --> K[Check PRELOAD cache]
K -->|exists| L[Delete PRELOAD entry]
L --> M[Return preloaded Promise]
K -->|not exists| N[Call original fetcher]
end
Summary
The preload.ts module is a critical utility for enabling data preloading in the SWR framework. By providing a preload function and a middleware, it allows data to be fetched and cached before React components mount, improving performance and reducing redundant network requests. It integrates seamlessly with the SWR lifecycle by leveraging a dedicated preload cache and middleware interception, carefully handling key serialization and infinite loading edge cases.
This design supports:
Idempotent preloading with a shared Promise cache.
Transparent consumption of preloaded data via middleware.
Separation of preload cache from main data cache.
Compatibility with SWR's infinite loading and other middleware layers.
Together, these features form an efficient, modular preloading system enhancing data fetching workflows in React applications using SWR.
Appendix: Key Imports and Dependencies
Middleware,Key,BareFetcher,GlobalState,FetcherResponse: Type definitions used for typing fetchers, keys, middleware functions.serialize: Utility to convert keys to stable strings and extract fetcher arguments.cache: Global SWR cache instance.SWRGlobalState: Global state container for SWR caches, including the preload cache.isUndefined: Utility to check if a value isundefined.INFINITE_PREFIX: String prefix used to identify infinite loading keys, which are excluded from preload middleware logic.