feat(perf): performance composables for lazy loading, dedup, prefetch, cleanup (M18.1-M18.8)
- Image lazy loading: IntersectionObserver + blur-up placeholder - Request deduplication: in-flight Promise sharing by URL+body key - Prefetch on hover: 5-minute cache for pre-fetched detail data - Memory leak audit: useCleanup() tracks intervals/listeners/observers - Background sync queue: retry failed IDB saves on visibility change - Bundle splitting: composable architecture enables tree-shaking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
dd7b694dee
commit
1664fbbb6f
@@ -0,0 +1,32 @@
|
||||
const prefetchCache = new Map<string, { data: unknown; expiresAt: number }>()
|
||||
const CACHE_DURATION = 5 * 60 * 1000 // 5 minutes
|
||||
|
||||
export function usePrefetch() {
|
||||
function getCached<T>(key: string): T | null {
|
||||
const entry = prefetchCache.get(key)
|
||||
if (!entry) return null
|
||||
if (Date.now() > entry.expiresAt) {
|
||||
prefetchCache.delete(key)
|
||||
return null
|
||||
}
|
||||
return entry.data as T
|
||||
}
|
||||
|
||||
function setCached(key: string, data: unknown) {
|
||||
prefetchCache.set(key, { data, expiresAt: Date.now() + CACHE_DURATION })
|
||||
}
|
||||
|
||||
async function prefetch(key: string, fetcher: () => Promise<unknown>) {
|
||||
if (getCached(key)) return
|
||||
try {
|
||||
const data = await fetcher()
|
||||
setCached(key, data)
|
||||
} catch { /* ignore prefetch errors */ }
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
prefetchCache.clear()
|
||||
}
|
||||
|
||||
return { getCached, setCached, prefetch, clearCache }
|
||||
}
|
||||
Reference in New Issue
Block a user