Skip to content
Latestv1.0.63

Cache Strategy

@yh-ui/request provides multi-layered cache solutions including in-memory caching, persistent caching (localStorage/IndexedDB), and out-of-the-box SWR strategy.

Cache Types

Memory Cache

Memory cache is the default caching method with the fastest speed, but data is lost after the page closes.

typescript
import { MemoryCache } from '@yh-ui/request'

const cache = new MemoryCache({
  maxSize: 100, // Max cache entries
  maxAge: 5 * 60 * 1000 // Cache validity: 5 minutes
})

// Set cache
cache.set('user_1', { id: 1, name: 'John' })

// Get cache
const user = cache.get('user_1')

// Delete cache
cache.delete('user_1')

// Clear all cache
cache.clear()

LocalStorage Cache

Suitable for small amounts of persistent storage, with a limit of about 5MB.

typescript
import { LocalStorageCache } from '@yh-ui/request'

const cache = new LocalStorageCache({
  prefix: 'yh_request_', // Storage key prefix
  maxAge: 24 * 60 * 60 * 1000 // Cache validity: 1 day
})

// Same usage as MemoryCache
cache.set('api_data', { foo: 'bar' })
const data = cache.get('api_data')

IndexedDB Cache

Suitable for large amounts of persistent storage with larger capacity (typically hundreds of MB).

typescript
import { IndexedDBCache } from '@yh-ui/request'

const cache = new IndexedDBCache({
  dbName: 'yh-request-cache', // Database name
  storeName: 'api-cache', // Object store name
  maxSize: 100 * 1024 * 1024, // Max capacity: 100MB
  maxAge: 7 * 24 * 60 * 60 * 1000 // Cache validity: 7 days
})

// Async operations
await cache.set('large_data', { huge: 'object' })
const data = await cache.get('large_data')

Cache Factory

Use createCache factory function to create cache instances by type:

typescript
import { createCache, type CacheType } from '@yh-ui/request'

// Create memory cache
const memoryCache = createCache('memory')

// Create localStorage cache
const lsCache = createCache('localStorage')

// Create IndexedDB cache
const idbCache = createCache('indexedDB')

Using Cache in Requests

Manual Caching

Implement request caching through interceptors:

typescript
import { request, MemoryCache } from '@yh-ui/request'

const apiCache = new MemoryCache()

// Request interceptor - check cache
request.interceptors.request.use(async (config) => {
  const cacheKey = config.url + JSON.stringify(config.params)

  // If GET request and has cache, return cached data
  if (config.method === 'GET') {
    const cached = apiCache.get(cacheKey)
    if (cached) {
      return { ...config, cacheData: cached }
    }
  }
  return config
})

// Response interceptor - store cache
request.interceptors.response.use((response) => {
  const cacheKey = response.config.url + JSON.stringify(response.config.params)

  if (response.config.method === 'GET') {
    apiCache.set(cacheKey, response.data)
  }
  return response
})

Auto-Cache Configuration

Specify cache strategy in request configuration:

typescript
const response = await request.get('/api/users', {
  // Enable cache
  cache: true,
  // Cache validity (ms)
  cacheTime: 5 * 60 * 1000,
  // Cache key
  cacheKey: 'users_list'
})

SWR Strategy

SWR (Stale-While-Revalidate) is a powerful caching strategy: return cached data first (even if stale), then revalidate in the background.

typescript
import { useRequest } from '@yh-ui/request'

// Basic SWR usage
const { data, loading, error } = useRequest(() => fetchUsers(), {
  swr: true, // Enable SWR mode
  cacheKey: 'users_list', // Cache key
  staleTime: 5 * 60 * 1000, // Fresh time: no re-request within 5 minutes
  cacheTime: 30 * 60 * 1000, // Cache retention: 30 minutes
  refreshOnWindowFocus: true, // Re-request on window focus
  refreshDeps: [() => userId] // Re-request when dependencies change
})

SWR Configuration Options

OptionDescriptionDefault
swrEnable SWR modefalse
cacheKeyUnique cache identifierAuto-generated
staleTimeData freshness time (ms)0
cacheTimeCache retention time (ms)5 * 60 * 1000
refreshOnWindowFocusRe-request on window focusfalse
refreshDepsDependency array, re-request on change[]
refreshDepsWaitDebounce wait on dependency change (ms)300

SWR How It Works

1. First request:
   → No cache → Make request → Return data → Store in cache

2. Subsequent requests (within staleTime):
   → Has cache → Return cached data directly → No request made

3. Subsequent requests (after staleTime):
   → Has cache → Return cached data (stale) → Background request → Update cache

4. Window focus (refreshOnWindowFocus: true):
   → Re-request → Update cache and UI

Cache Invalidation

Invalidate by Key

typescript
// Delete specific cache
apiCache.delete('users_list')

// Clear all cache
apiCache.clear()

Tag-based Invalidation

typescript
// Set tags for cache
cache.set('user_1', userData, { tags: ['users', 'profile'] })
cache.set('user_2', userData, { tags: ['users'] })

// Clear by tag
cache.clearByTag('users') // Clear all caches with 'users' tag

ETag Support

Implement HTTP-level cache negotiation through response headers:

typescript
// Request with If-None-Match
request.interceptors.request.use((config) => {
  const cached = cache.get(config.url)
  if (cached?.etag) {
    config.headers['If-None-Match'] = cached.etag
  }
  return config
})

// Check 304 in response
request.interceptors.response.use((response) => {
  const etag = response.response.headers.get('ETag')
  if (etag && response.response.status === 304) {
    const cached = cache.get(response.config.url!)
    if (cached) {
      return { ...response, data: cached.data }
    }
  }
  // Store new data and ETag
  cache.set(response.config.url!, { data: response.data, etag })
  return response
})

Best Practices

1. Set Cache Time Appropriately

typescript
// Frequently changing data: no cache or short cache
const { data } = await request.get('/api/stock/price', {
  staleTime: 0
})

// Relatively stable data: longer cache
const { data } = await request.get('/api/config/app', {
  staleTime: 30 * 60 * 1000 // 30 minutes
})

2. Differentiate Cache Granularity

typescript
// List page cache - differentiate by pagination params
const cacheKey = `users_list_page_${page}_size_${pageSize}`

// Detail page cache - differentiate by ID
const cacheKey = `user_detail_${userId}`

3. Clear Cache After Login

typescript
// Clear user-related cache after successful login
const handleLogin = async () => {
  await login()
  // Clear all user-related cache
  apiCache.clearByTag('users')
}

Interactive Cache Demo

Test the performance improvement of in-memory caching in the example below. You can adjust the Cache TTL, send requests multiple times, and observe the duration difference between cache hit (instant) vs cache miss (network delay), as well as the active cache TTL countdown.

API Request Cache Simulator

Next Steps

Released under the MIT License.