以下是前端数据缓存的完整解决方案,涵盖策略设计、技术实现和性能优化:
一、缓存策略分层设计
二、核心场景实现方案
1. 高频请求数据缓存(内存缓存)
// 使用Map实现LRU缓存
class MemoryCache {
constructor(maxSize = 100) {
this.cache = new Map()
this.maxSize = maxSize
}
get(key) {
const item = this.cache.get(key)
if (item) {
// 更新访问顺序
this.cache.delete(key)
this.cache.set(key, item)
}
return item?.value
}
set(key, value, ttl = 60_000) {
if (this.cache.size >= this.maxSize) {
// 删除最久未使用的
const oldestKey = this.cache.keys().next().value
this.cache.delete(oldestKey)
}
this.cache.set(key, {
value,
expire: Date.now() + ttl
})
}
clearExpired() {
const now = Date.now()
for (const [key, { expire }] of this.cache) {
if (now > expire) this.cache.delete(key)
}
}
}
// 使用示例
const apiCache = new MemoryCache(50)
2. 持久化重要数据(LocalStorage + 版本控制)
const CACHE_VERSION = 'v1.3'
function getCache(key) {
try {
const data = localStorage.getItem(`${CACHE_VERSION}_${key}`)
return data ? JSON.parse(data) : null
} catch (error) {
console.error('缓存读取失败', error)
return null
}
}
function setCache(key, value, ttl = 3600_000) {
const data = {
value,
expire: Date.now() + ttl,
timestamp: Date.now()
}
localStorage.setItem(
`${CACHE_VERSION}_${key}`,
JSON.stringify(data)
)
}
// 定时清理过期缓存
setInterval(() => {
Object.keys(localStorage).forEach(key => {
if (key.startsWith(CACHE_VERSION)) {
const data = JSON.parse(localStorage.getItem(key))
if (data?.expire < Date.now()) {
localStorage.removeItem(key)
}
}
})
}, 60_000)
3. 接口请求缓存策略
const apiCache = new Map()
async function cachedFetch(url, options = {}) {
const cacheKey = JSON.stringify({ url, options })
// 命中缓存
if (apiCache.has(cacheKey)) {
const { expire, data } = apiCache.get(cacheKey)
if (Date.now() < expire) return data.clone()
}
// 发起真实请求
const response = await fetch(url, options)
const cloneRes = response.clone()
// 缓存新数据
apiCache.set(cacheKey, {
data: cloneRes,
expire: Date.now() + (options.ttl || 300_000)
})
return response
}
三、高级缓存模式
1. 缓存分层策略
async function getData(key) {
// 第一层:内存缓存
let data = memoryCache.get(key)
if (data) return data
// 第二层:本地存储
data = getLocalCache(key)
if (data) {
memoryCache.set(key, data)
return data
}
// 第三层:网络请求
data = await fetchData(key)
memoryCache.set(key, data)
setLocalCache(key, data)
return data
}
2. 缓存更新策略
// Stale-While-Revalidate 模式
function swrFetch(url, ttl = 300_000) {
const cached = getCache(url)
// 立即返回过期数据,后台更新
if (cached) {
if (Date.now() < cached.expire) {
return Promise.resolve(cached.value)
} else {
fetch(url)
.then(updateCache)
.catch(console.error)
return cached.value
}
}
// 无缓存则正常请求
return fetch(url).then(updateCache)
}
四、性能优化方案
1. Web Worker 缓存处理
// 主线程
const worker = new Worker('cache-worker.js')
worker.postMessage({
type: 'SET_CACHE',
key: 'userData',
value: userData
})
// Worker线程处理
self.onmessage = (e) => {
if (e.data.type === 'SET_CACHE') {
IndexedDB.set(e.data.key, e.data.value)
}
}
2. 缓存压缩策略
function compressData(data) {
const str = JSON.stringify(data)
const compressed = LZString.compress(str)
return compressed
}
function decompressData(compressed) {
const str = LZString.decompress(compressed)
return JSON.parse(str)
}
五、缓存监控与调试
1. 缓存命中率统计
const cacheStats = {
total: 0,
hits: 0,
misses: 0
}
function trackCacheAccess(isHit) {
cacheStats.total++
isHit ? cacheStats.hits++ : cacheStats.misses++
if (cacheStats.total % 100 === 0) {
console.log(`缓存命中率: ${(cacheStats.hits/cacheStats.total*100).toFixed(1)}%`)
}
}
2. Chrome DevTools 调试
// 暴露缓存接口到全局
window.__debugCache = {
clear: () => {
memoryCache.clear()
localStorage.clear()
},
stats: () => cacheStats
}
六、最佳实践建议
-
缓存Key设计原则
// 好的Key设计示例 const getCacheKey = (apiPath, params) => { const sortedParams = Object.keys(params) .sort() .map(k => `${k}=${params[k]}`) .join('&') return `api_${apiPath}?${sortedParams}` }
-
敏感数据处理
// 加密敏感缓存 import CryptoJS from 'crypto-js' function secureSet(key, value) { const encrypted = CryptoJS.AES.encrypt( JSON.stringify(value), process.env.CACHE_SECRET ).toString() localStorage.setItem(key, encrypted) }
-
缓存容量控制
// IndexedDB容量监测 navigator.storage.estimate().then(estimate => { console.log(`已使用: ${estimate.usage/1024/1024}MB`) console.log(`限额: ${estimate.quota/1024/1024}MB`) })
七、不同场景推荐方案
场景 | 推荐方案 | 优势 | 注意事项 |
---|---|---|---|
高频更新数据 | 内存缓存 | 访问速度快 | 需设置合理TTL |
大型数据集 | IndexedDB | 支持结构化存储 | 需处理版本迁移 |
离线优先 | Service Worker | 网络不可用仍可访问 | 需处理缓存更新 |
敏感信息 | 加密存储 | 数据安全 | 加解密性能损耗 |
通过合理使用这些缓存策略,可以实现:
- 首屏加载速度提升 30%-70% ⚡
- 接口请求量减少 40%+ 📉
- 离线场景正常使用 📴
- 流量消耗显著降低 🌐
建议结合业务需求选择缓存层级,并定期通过 window.performance.memory
监控内存使用情况,避免过度缓存导致内存泄漏。