缓存策略规范
缓存策略是前端性能优化的重要手段,合理的工程化规范能确保缓存机制高效可控。从本地存储到HTTP缓存,不同场景需要针对性设计,同时避免常见陷阱。
本地存储规范
本地存储包括localStorage、sessionStorage和IndexedDB,适用于需要持久化或大量结构化数据的场景。工程实践中需建立明确的存储命名规范:
// 项目前缀+模块名+业务键名 三级命名规范
const STORAGE_KEY = 'PROJ_USER_TOKEN';
const HISTORY_KEY = 'PROJ_SEARCH_HISTORY';
// 封装统一操作接口
export const storage = {
set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
console.error('LocalStorage写入失败', e);
// 自动降级处理
sessionStorage.setItem(key, JSON.stringify(value));
}
},
get(key) {
const data = localStorage.getItem(key) || sessionStorage.getItem(key);
try {
return data ? JSON.parse(data) : null;
} catch {
return data; // 兼容非JSON数据
}
}
};
容量控制策略:
- 单个域名下localStorage限制通常为5MB
- 超过阈值时采用LRU算法自动清理
- 敏感数据需设置自动过期时间
// LRU缓存实现示例
class LRUCache {
constructor(maxSize) {
this.cache = new Map();
this.maxSize = maxSize;
}
get(key) {
if (!this.cache.has(key)) return null;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
set(key, value) {
if (this.cache.size >= this.maxSize) {
const oldestKey = this.cache.keys().next().value;
this.cache.delete(oldestKey);
}
this.cache.set(key, value);
}
}
HTTP缓存策略设计
HTTP缓存分为强缓存和协商缓存,需根据资源类型配置不同策略:
强缓存配置示例(Nginx):
location ~* \.(js|css|png)$ {
expires 365d;
add_header Cache-Control "public, max-age=31536000, immutable";
}
动态资源协商缓存配置:
location /api {
add_header Cache-Control "no-cache";
etag on;
}
缓存更新策略对比:
策略类型 | 实现方式 | 适用场景 | 示例 |
---|---|---|---|
文件名哈希 | 构建工具生成hash文件名 | 静态资源 | app.3a7b8c.js |
查询参数版本 | URL追加?v=1.0.0 | 第三方库 | lib.js?v=2.1.4 |
路径版本控制 | 版本化目录结构 | 多环境部署 | /v2/assets/logo.png |
后台推送更新 | Service Worker控制 | PWA应用 | self.skipWaiting() |
Service Worker缓存策略
Service Worker提供精细的缓存控制能力,常用策略包括:
缓存优先网络回退方案:
// sw.js
const CACHE_NAME = 'v1';
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cached) => {
return cached || fetch(event.request).then((response) => {
// 动态缓存非GET请求和opaque响应
if (event.request.method !== 'GET' || response.status === 0) {
return response;
}
const responseToCache = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, responseToCache);
});
return response;
}).catch(() => {
// 网络失败时返回备用内容
return new Response('离线备用内容');
});
})
);
});
预缓存关键资源:
// 构建时生成的预缓存列表
const PRE_CACHE_LIST = [
'/css/main.css',
'/js/app.js',
'/offline.html'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRE_CACHE_LIST))
.then(() => self.skipWaiting())
);
});
缓存更新与失效机制
有效的缓存失效策略是工程化重点:
版本号控制方案:
// webpack配置示例
output: {
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js'
}
API请求缓存控制:
// 封装带缓存的fetch
const apiCache = new Map();
async function cachedFetch(url, options = {}) {
const cacheKey = `${url}_${JSON.stringify(options)}`;
// 检查内存缓存
if (apiCache.has(cacheKey)) {
const { data, timestamp } = apiCache.get(cacheKey);
if (Date.now() - timestamp < 300000) { // 5分钟有效期
return data;
}
}
// 实际请求
try {
const res = await fetch(url, options);
const data = await res.json();
// 更新缓存
apiCache.set(cacheKey, {
data,
timestamp: Date.now()
});
return data;
} catch (error) {
// 失败时返回缓存数据(如果有)
if (apiCache.has(cacheKey)) {
return apiCache.get(cacheKey).data;
}
throw error;
}
}
特殊场景处理
表单提交防重复缓存:
<!-- 使用autocomplete控制 -->
<form autocomplete="off">
<input type="text" name="key" autocomplete="new-password">
</form>
视频分段缓存策略:
// MediaSource扩展缓冲
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', () => {
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"');
fetch('/video/segment1.mp4').then(response => {
return response.arrayBuffer();
}).then(data => {
sourceBuffer.appendBuffer(data);
});
});
监控与异常处理
建立缓存健康度监控体系:
// 缓存命中率统计
window.addEventListener('load', () => {
const timing = performance.getEntriesByType('navigation')[0];
const cacheRatio = (timing.transferSize - timing.encodedBodySize) / timing.transferSize;
analytics.send('cache_hit_ratio', cacheRatio);
});
// 缓存异常监控
window.addEventListener('error', (e) => {
if (e.message.includes('QuotaExceededError')) {
metrics.increment('storage.quota_exceeded');
}
});
多环境差异化配置
不同环境应采用不同缓存策略:
// 环境检测与策略切换
const getCacheStrategy = () => {
if (process.env.NODE_ENV === 'development') {
return {
apiCacheTTL: 0,
staticAssets: 'no-store'
};
}
if (location.host.includes('staging')) {
return {
apiCacheTTL: 300000,
staticAssets: 'max-age=300'
};
}
return {
apiCacheTTL: 3600000,
staticAssets: 'max-age=31536000'
};
};
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:静态资源处理
下一篇:Webpack的定义与作用