前端缓存策略:让你的网站飞起来
毒舌时刻
前端缓存?这不是浏览器的事吗?
"我不需要管缓存,浏览器会自动处理"——结果网站加载慢,用户体验差,
"缓存就是localStorage嘛,多简单"——结果缓存管理混乱,内存占用高,
"我直接禁用缓存,省得麻烦"——结果每次都重新加载,浪费带宽。
醒醒吧,前端缓存不是简单的localStorage,而是一套完整的策略!
为什么你需要这个?
- 性能提升:减少重复请求,加快页面加载速度
- 用户体验:离线访问,减少等待时间
- 带宽节省:减少服务器流量,降低成本
- 可靠性:网络不稳定时仍能正常访问
反面教材
// 反面教材:滥用localStorage function fetchData() { // 每次都从API获取数据 return fetch('https://api.example.com/data') .then(res => res.json()) .then(data => { // 直接存储到localStorage localStorage.setItem('data', JSON.stringify(data)); return data; }); } // 反面教材:没有缓存失效策略 function getCachedData() { // 永远使用缓存,不考虑过期 const cachedData = localStorage.getItem('data'); return cachedData ? JSON.parse(cachedData) : null; } // 反面教材:缓存键命名混乱 function cacheData(key, data) { // 缓存键没有统一规范 localStorage.setItem(`cache_${key}_${Date.now()}`, JSON.stringify(data)); }
正确的做法
// 正确的做法:完整的缓存策略 class CacheManager { constructor() { this.cachePrefix = 'app_cache_'; this.defaultExpiry = 24 * 60 * 60 * 1000; // 24小时 } // 生成缓存键 generateKey(key) { return `${this.cachePrefix}${key}`; } // 存储数据到缓存 set(key, data, expiry = this.defaultExpiry) { const cacheItem = { data, expiry: Date.now() + expiry, timestamp: Date.now() }; try { localStorage.setItem(this.generateKey(key), JSON.stringify(cacheItem)); } catch () { console.(, ); // 处理存储空间不足的情况 this.clearOldCache(); } } // 从缓存获取数据 get(key) { const cacheItem = localStorage.getItem(this.generateKey(key)); (!cacheItem) { null; } try { const parsedItem = JSON.parse(cacheItem); // 检查是否过期 (Date.now() > parsedItem.expiry) { this.(key); null; } parsedItem.data; } catch () { console.(, ); this.(key); null; } } // 移除缓存 (key) { localStorage.removeItem(this.generateKey(key)); } // 清空所有缓存 clear() { Object.keys(localStorage).forEach(key => { (key.startsWith(this.cachePrefix)) { localStorage.removeItem(key); } }); } // 清理过期缓存 clearOldCache() { Object.keys(localStorage).forEach(key => { (key.startsWith(this.cachePrefix)) { try { const item = JSON.parse(localStorage.getItem(key)); (Date.now() > item.expiry) { localStorage.removeItem(key); } } catch () { localStorage.removeItem(key); } } }); } // 获取缓存大小 getCacheSize() { let size = ; Object.keys(localStorage).forEach(key => { (key.startsWith(this.cachePrefix)) { size += localStorage.getItem(key).length; } }); size; } } // 正确的做法:使用Service Worker缓存 // service-worker.js const CACHE_NAME = ; const ASSETS_TO_CACHE = [ , , , , , ]; // 安装Service Worker .addEventListener(, event => { event.waitUntil( caches.(CACHE_NAME) .(cache => { console.(); cache.addAll(ASSETS_TO_CACHE); }) ); }); // 激活Service Worker .addEventListener(, event => { const cacheWhitelist = [CACHE_NAME]; event.waitUntil( caches.keys().(cacheNames => { Promise.all( cacheNames.map(cacheName => { (cacheWhitelist.indexOf(cacheName) === ) { caches.delete(cacheName); } }) ); }) ); }); // 拦截网络请求 .addEventListener(, event => { event.respondWith( caches.(event.request) .(response => { // 如果缓存中有响应,直接返回 (response) { response; } // 否则发起网络请求 fetch(event.request) .(response => { // 如果响应有效,缓存一份 (response && response. === && response. === ) { const responseToCache = response.clone(); caches.(CACHE_NAME) .(cache => { cache.put(event.request, responseToCache); }); } response; }); }) ); }); // 正确的做法:API请求缓存 async { const cacheKey = `api_${url}_${JSON.stringify(options)}`; const cacheManager = new CacheManager(); // 尝试从缓存获取 const cachedData = cacheManager.get(cacheKey); (cachedData) { cachedData; } // 发起网络请求 const response = await fetch(url, options); const data = await response.json(); // 缓存数据 cacheManager.set(cacheKey, data, * * ); // 分钟过期 data; }

