前端性能优化缓存策略完全指南前言嘿各位前端小伙伴今天我们来聊聊前端性能优化中最核心的技术之一——缓存策略。缓存就像是一个神奇的魔法箱它可以让你的应用运行得更快、更流畅。想象一下你每次去超市买东西如果每次都要去仓库取货那该多慢啊缓存就像是超市的货架把常用的商品放在最显眼的地方方便快速取用。一、缓存类型概览1.1 缓存层次结构interface CacheStrategy { type: memory | disk | service-worker | http; priority: number; ttl: number; // 过期时间秒 }1.2 缓存类型对比类型存储位置容量持久性访问速度内存缓存RAM小会话级最快磁盘缓存硬盘大持久较快Service Worker硬盘中持久中等HTTP缓存浏览器中持久较快二、HTTP缓存策略2.1 缓存头配置// HTTP响应头示例 const cacheHeaders { // 强制缓存 Cache-Control: max-age31536000, immutable, // 协商缓存 Last-Modified: Mon, 01 Jan 2024 00:00:00 GMT, ETag: abc123, // 禁止缓存 Cache-Control: no-cache, no-store, must-revalidate };2.2 缓存策略配置function getCacheStrategy(resourceType) { const strategies { // 静态资源长期缓存 static: { Cache-Control: public, max-age31536000, immutable }, // API数据短期缓存 api: { Cache-Control: public, max-age60, stale-while-revalidate300 }, // HTML页面协商缓存 html: { Cache-Control: no-cache, ETag: generateETag() }, // 用户数据不缓存 user-data: { Cache-Control: no-cache, no-store, must-revalidate } }; return strategies[resourceType] || strategies[static]; }三、Service Worker缓存3.1 基础缓存策略// service-worker.js const CACHE_NAME my-app-cache-v1; const ASSETS_TO_CACHE [ /, /index.html, /styles.css, /app.js, /logo.png ]; self.addEventListener(install, (event) { event.waitUntil( caches.open(CACHE_NAME) .then(cache cache.addAll(ASSETS_TO_CACHE)) .then(() self.skipWaiting()) ); }); self.addEventListener(activate, (event) { event.waitUntil( caches.keys().then(cacheNames { return Promise.all( cacheNames.filter(name name ! CACHE_NAME) .map(name caches.delete(name)) ); }) ); }); self.addEventListener(fetch, (event) { event.respondWith( caches.match(event.request) .then(cachedResponse { // 返回缓存或网络请求 return cachedResponse || fetch(event.request); }) ); });3.2 高级缓存策略// 网络优先策略 function networkFirst(request) { return fetch(request).then(networkResponse { // 更新缓存 caches.open(CACHE_NAME).then(cache { cache.put(request, networkResponse.clone()); }); return networkResponse; }).catch(() { // 网络失败时返回缓存 return caches.match(request); }); } // 缓存优先策略 function cacheFirst(request) { return caches.match(request).then(cachedResponse { if (cachedResponse) { return cachedResponse; } return fetch(request).then(networkResponse { caches.open(CACHE_NAME).then(cache { cache.put(request, networkResponse.clone()); }); return networkResponse; }); }); } // 策略路由 self.addEventListener(fetch, (event) { const request event.request; if (request.url.includes(/api/)) { event.respondWith(networkFirst(request)); } else { event.respondWith(cacheFirst(request)); } });四、内存缓存4.1 缓存管理器class MemoryCache { constructor(options {}) { this.cache new Map(); this.ttl options.ttl || 300000; // 默认5分钟 } set(key, value, ttl this.ttl) { const item { value, timestamp: Date.now(), ttl }; this.cache.set(key, item); // 自动过期 setTimeout(() { this.cache.delete(key); }, ttl); } get(key) { const item this.cache.get(key); if (!item) return null; // 检查是否过期 if (Date.now() - item.timestamp item.ttl) { this.cache.delete(key); return null; } return item.value; } has(key) { const item this.cache.get(key); if (!item) return false; if (Date.now() - item.timestamp item.ttl) { this.cache.delete(key); return false; } return true; } delete(key) { return this.cache.delete(key); } clear() { this.cache.clear(); } size() { return this.cache.size; } } const cache new MemoryCache({ ttl: 60000 });4.2 缓存键生成function generateCacheKey(request) { if (typeof request string) { return request; } return JSON.stringify({ url: request.url, method: request.method, body: request.body, headers: Object.fromEntries(request.headers.entries()) }); }五、数据缓存策略5.1 多层缓存class MultiLayerCache { constructor() { this.memoryCache new MemoryCache({ ttl: 60000 }); this.storageCache new LocalStorageCache(); } async get(key) { // 先从内存缓存获取 const memoryValue this.memoryCache.get(key); if (memoryValue ! null) { return memoryValue; } // 再从本地存储获取 const storageValue await this.storageCache.get(key); if (storageValue ! null) { // 更新内存缓存 this.memoryCache.set(key, storageValue); return storageValue; } return null; } async set(key, value, options {}) { // 设置内存缓存 this.memoryCache.set(key, value, options.ttl); // 设置本地存储 await this.storageCache.set(key, value, options.storageTtl); } }5.2 LocalStorage缓存class LocalStorageCache { constructor() { this.prefix app-cache:; } async get(key) { try { const item localStorage.getItem(this.prefix key); if (!item) return null; const parsed JSON.parse(item); // 检查过期时间 if (parsed.expires Date.now() parsed.expires) { localStorage.removeItem(this.prefix key); return null; } return parsed.value; } catch { return null; } } async set(key, value, ttl 86400000) { try { const item { value, expires: ttl ? Date.now() ttl : null }; localStorage.setItem(this.prefix key, JSON.stringify(item)); } catch { // 存储失败可能是空间不足 } } async delete(key) { localStorage.removeItem(this.prefix key); } }六、缓存失效策略6.1 时间过期function isCacheValid(cacheEntry) { if (!cacheEntry || !cacheEntry.timestamp) { return false; } const now Date.now(); const age now - cacheEntry.timestamp; return age cacheEntry.ttl; }6.2 版本控制const CACHE_VERSION v1.2.3; function getVersionedKey(key) { return ${CACHE_VERSION}:${key}; } function clearOldCaches() { const currentVersion CACHE_VERSION; Object.keys(localStorage).forEach(key { if (key.startsWith(app-cache:) !key.includes(currentVersion)) { localStorage.removeItem(key); } }); }6.3 主动失效class CacheInvalidator { constructor(cache) { this.cache cache; this.invalidationRules new Map(); } registerInvalidationRule(pattern, callback) { this.invalidationRules.set(pattern, callback); } invalidate(pattern) { const callback this.invalidationRules.get(pattern); if (callback) { callback(this.cache); } } invalidateAll() { this.cache.clear(); } } const invalidator new CacheInvalidator(cache); invalidator.registerInvalidationRule(user:*, (cache) { cache.keys().forEach(key { if (key.startsWith(user:)) { cache.delete(key); } }); });七、缓存最佳实践7.1 静态资源缓存// 构建时生成哈希文件名 const assets { styles.css: styles.abc123.css, app.js: app.def456.js, logo.png: logo.789ghi.png }; // HTML中引用带哈希的资源 function getAssetUrl(name) { return /assets/${assets[name]}; }7.2 API响应缓存class APICache { constructor() { this.cache new MemoryCache({ ttl: 60000 }); } async fetch(url, options {}) { const cacheKey generateCacheKey({ url, ...options }); // 检查缓存 const cached this.cache.get(cacheKey); if (cached) { return cached; } // 发起请求 const response await fetch(url, options); const data await response.json(); // 缓存响应 this.cache.set(cacheKey, data, options.ttl); return data; } invalidate(url) { this.cache.cache.forEach((_, key) { if (key.includes(url)) { this.cache.delete(key); } }); } }7.3 缓存统计class CacheStats { constructor() { this.hits 0; this.misses 0; } recordHit() { this.hits; } recordMiss() { this.misses; } get hitRate() { const total this.hits this.misses; return total 0 ? (this.hits / total * 100).toFixed(2) : 0.00; } reset() { this.hits 0; this.misses 0; } } const stats new CacheStats(); // 使用统计 const cached cache.get(key); if (cached) { stats.recordHit(); } else { stats.recordMiss(); }八、性能对比8.1 缓存 vs 非缓存指标非缓存缓存网络请求数多少响应时间长短带宽消耗高低服务器负载高低离线支持无有8.2 缓存策略对比策略优点缺点适用场景内存缓存最快容量小高频访问数据磁盘缓存容量大较慢低频访问数据Service Worker离线支持复杂PWA应用HTTP缓存浏览器原生配置复杂静态资源九、总结缓存策略是前端性能优化的核心HTTP缓存利用浏览器原生缓存机制Service Worker实现离线支持和高级缓存策略内存缓存快速访问高频数据本地存储持久化缓存低频数据通过合理的缓存策略我们可以减少网络请求降低响应时间支持离线访问减轻服务器负载延伸阅读HTTP CachingService Worker APICache API如果你喜欢这篇文章请点赞、收藏、关注三连你的支持是我创作的最大动力