cache.ts
Overview
The cache.ts file is a core utility module responsible for initializing and managing cache providers within the SWR (stale-while-revalidate) data fetching ecosystem. It orchestrates the creation and lifecycle of global state associated with a cache provider, including:
Managing subscriptions to cache key changes.
Providing a scoped mutation function to update cache entries and trigger revalidations.
Setting up global event listeners (e.g., window focus and network reconnect) that cause automatic revalidation of cached data.
Ensuring deduplication and centralized event-driven cache updates.
This module enables efficient coordination between multiple components sharing the same cache provider, allowing them to reactively update when cached data changes or when revalidation events occur.
Detailed Explanation
Key Concepts
Cache Provider: A key-value store (typically a
Mapor similar) that holds cached data entries identified by keys.Global State: A centralized state object associated with each cache provider that tracks event revalidators, subscriptions, and the mutate function.
Revalidators: Callbacks tied to cache keys that trigger revalidation logic.
Subscriptions: Callbacks that notify subscribers when the cached value of a key changes.
Mutate Function: A function bound to the cache provider that can update cached values and optionally trigger revalidation.
Event Listeners: Hooks that listen to global events like window focus or network reconnect to refresh the cache.
Functions and Exports
revalidateAllKeys
const revalidateAllKeys = (
revalidators: Record<string, RevalidateCallback[]>,
type: RevalidateEvent
) => { ... }
Purpose: Iterates over all registered revalidators and triggers the first callback for each key, passing the revalidation event type.
Parameters:
revalidators: An object mapping cache keys to arrays of revalidation callbacks.type: The type of revalidation event (e.g., focus, reconnect).
Return:
voidUsage: Internally used to trigger revalidation callbacks for all keys upon events like window focus or network reconnect.
initCache
export const initCache = <Data = any>(
provider: Cache<Data>,
options?: Partial<ProviderConfiguration>
):
| [Cache<Data>, ScopedMutator, () => void, () => void]
| [Cache<Data>, ScopedMutator]
| undefined => { ... }
Purpose: Initializes or retrieves the global state bound to a cache provider, setting up mutation and subscription mechanisms as well as event listeners for automatic revalidation.
Parameters:
provider: The cache provider to be initialized or retrieved. Typically aMap-like interface.options?: Optional configuration overrides for provider initialization (e.g., event listener hooks).
Returns:
If the provider is new: a tuple containing:
The cache
provider.A scoped
mutatefunction bound to the provider.An
initProviderfunction to (re)initialize global state and event listeners.An
unmountfunction to clean up event listeners and global state on teardown.
If the provider already exists: a tuple containing just the cache
providerand the scopedmutatefunction.undefinedif no provider is passed.
Internal Implementation Details
Global State Storage:
Uses a globalSWRGlobalStateWeakMapkeyed by the cache provider, storing:EVENT_REVALIDATORS: Map of keys to revalidation callbacks.Several empty objects for internal usage (unused in this snippet).
mutate: The scoped mutation function.setter: Function to update cache values and notify subscribers.subscribe: Function to subscribe to cache key changes.
Subscriptions:
Asubscriptionsobject tracks arrays of callbacks per cache key. When a key’s value updates viasetter, all subscribers are notified with the new and previous value.Mutate Function:
Created by binding the internalinternalMutatefunction to the provided cache, enabling cache updates and revalidations scoped to this provider.Event Listeners:
Initialized only if not running on the server (
IS_SERVER === false).Listeners for focus and reconnect events are set up with a slight delay using
setTimeoutto avoid triggering revalidation during immediate React state updates.These listeners call
revalidateAllKeys, which triggers revalidation callbacks for all keys.unmountfunction cleans up these listeners and removes the provider from the global state to prevent memory leaks.
Provider Initialization Workflow:
If the provider is not already registered, the function creates global state and event listeners.
If it is already registered, it returns existing mutate function and provider for reuse.
Usage Example
import { initCache } from './cache'
// Assume `myCache` is a Map or compatible cache provider.
const myCache = new Map<string, any>()
// Initialize the cache provider
const [provider, mutate, initProvider, unmount] = initCache(myCache, {
// Optional config overrides
initFocus: (callback) => {
window.addEventListener('focus', callback)
return () => window.removeEventListener('focus', callback)
},
initReconnect: (callback) => {
window.addEventListener('online', callback)
return () => window.removeEventListener('online', callback)
}
})!
// Subscribe to changes of a key
const unsubscribe = (SWRGlobalState.get(provider) as any)[6]('some-key', (current, prev) => {
console.log('Cache value changed:', prev, '->', current)
})
// Mutate cache entry and trigger revalidation
mutate('some-key', async () => {
const data = await fetchData()
return data
})
// Later, cleanup event listeners on unmount
unmount()
How This File Interacts with the System
With Cache Providers:
This file initializes cache providers, which are fundamental for storing and retrieving cached data in the SWR ecosystem.With Mutation Logic (
internalMutate):
The scopedmutatefunction created here delegates tointernalMutate, facilitating cache updates and triggering revalidation as needed.With Global State (
SWRGlobalState):
It maintains and manipulates global state entries keyed by cache providers, enabling shared cache coordination across components.With Revalidation Events:
Listens to global browser events (focus, reconnect) via hooks defined in the configuration to trigger background revalidation of cached data.With React SWR Hooks (e.g.,
useSWR):
Provides the underlying cache and mutation mechanisms thatuseSWRhooks consume to maintain reactive data fetching states.
Mermaid Class Diagram
classDiagram
class CacheProvider {
<<interface>>
+get(key: string): any
+set(key: string, value: any): void
+delete(key: string): void
}
class CacheState {
-EVENT_REVALIDATORS: Record<string, RevalidateCallback[]>
-subscriptions: Record<string, ((current: any, prev: any) => void)[]>
-mutate: ScopedMutator
-setter(key: string, value: any, prev: any): void
-subscribe(key: string, callback: (current: any, prev: any) => void): () => void
-unmount(): void
-initProvider(): void
}
class CacheInitializer {
+initCache(provider: CacheProvider, options?): [CacheProvider, ScopedMutator, () => void, () => void] | [CacheProvider, ScopedMutator] | undefined
}
CacheInitializer --> CacheState : creates/manages
CacheState *-- CacheProvider : uses
Summary
The cache.ts module is a foundational piece in the SWR architecture, responsible for:
Initializing and managing cache providers and their global state.
Providing a subscription model to listen for cache key changes.
Creating a scoped mutation function bound to the cache.
Setting up event listeners for automatic revalidation on user focus and network reconnect.
Managing lifecycle and cleanup of cache-related event listeners and global state.
By abstracting these concerns, the module enables efficient, reactive, and event-driven cache management that supports the stale-while-revalidate strategy of the broader SWR data fetching system.