前端缓存全解析:提升性能的关键策略

前端缓存技术深度解析:从原理到实践

目录

  1. 缓存概述
  2. HTTP 缓存(浏览器缓存)
  3. Service Worker 缓存
  4. 内存缓存
  5. 状态管理缓存
  6. 浏览器存储缓存
  7. 缓存策略详解
  8. 实际应用场景
  9. 性能优化实践
  10. 缓存失效与更新
  11. 常见问题与解决方案
  12. 最佳实践
  13. 总结

缓存概述

什么是缓存

缓存(Cache)是一种存储数据的技术,其核心目标是通过存储数据的副本,在后续请求中直接返回这些副本,从而提高数据访问速度和系统性能。

为什么需要缓存

在 Web 应用中,缓存的重要性不言而喻:

无缓存场景: 用户请求 → 服务器处理 → 数据库查询 → 数据处理 → 响应返回 ↑ ↓ 慢(多次网络往返 + 复杂计算) 耗时:500-2000ms 有缓存场景: 用户请求 → 缓存检查 → 直接返回 ↑ ↓ 快(内存访问) 耗时:1-50ms 

缓存的优势

  1. 提升性能:减少网络请求,加快页面加载速度
  2. 降低服务器负载:减少数据库查询和计算
  3. 节省带宽:减少数据传输量
  4. 改善用户体验:离线可用,快速响应
  5. 降低成本:减少服务器资源消耗

缓存的挑战

  1. 数据一致性:缓存数据可能与源数据不同步
  2. 缓存穿透:请求不存在的数据导致缓存失效
  3. 缓存雪崩:大量缓存同时失效导致请求涌入后端
  4. 缓存击穿:热点数据失效时大量请求直达数据库
  5. 存储空间限制:浏览器存储空间有限

缓存层级模型

┌─────────────────────────────────────┐ │ 用户请求 │ └─────────────────┬───────────────────┘ │ ┌─────────────────▼───────────────────┐ │ 浏览器缓存 │ │ ┌──────────┐ ┌──────────┐ │ │ │ HTTP │ │ Service │ │ │ │ 缓存 │ │ Worker │ │ │ └──────────┘ └──────────┘ │ └─────────────────┬───────────────────┘ │ ┌─────────────────▼───────────────────┐ │ 应用内存缓存 │ │ ┌──────────────────────┐ │ │ │ React/Vue │ │ │ │ 状态缓存 │ │ │ └──────────────────────┘ │ └─────────────────┬───────────────────┘ │ ┌─────────────────▼───────────────────┐ │ 服务器缓存 │ │ ┌──────────────────────┐ │ │ │ Redis / Memcached │ │ │ └──────────────────────┘ │ └─────────────────┬───────────────────┘ │ ┌─────────────────▼───────────────────┐ │ 数据库缓存 │ │ ┌──────────────────────┐ │ │ │ 查询结果缓存 │ │ │ └──────────────────────┘ │ └─────────────────────────────────────┘ 

HTTP 缓存(浏览器缓存)

HTTP 缓存是浏览器最基础的缓存机制,通过 HTTP 头信息控制资源的缓存行为。

1. 强缓存

强缓存(Strong Cache)不会向服务器发送请求,直接从缓存中获取资源。

Cache-Control
Cache-Control: max-age=3600 

常用指令:

  • max-age=<seconds>:缓存有效期(秒)
  • no-cache:需要验证缓存有效性
  • no-store:完全不使用缓存
  • public:响应可被任何缓存存储
  • private:响应只能被私有缓存存储
  • immutable:资源不会更新
// Node.js 服务器端设置 app.get('/api/data',(req, res)=>{ res.set('Cache-Control','public, max-age=3600');// 缓存1小时 res.json({data:'some data'});});// 静态资源长期缓存 app.use('/static', express.static('public',{setHeaders:(res, path)=>{ res.set('Cache-Control','public, max-age=31536000, immutable');}}));
# Nginx 配置 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; } location /api/ { expires 5m; add_header Cache-Control "public"; } 
Expires
Expires: Wed, 21 Oct 2026 07:28:00 GMT 
// 设置过期时间 res.set('Expires',newDate(Date.now()+3600000).toUTCString());

注意:Expires 是 HTTP/1.0 的产物,Cache-Control 是 HTTP/1.1 的改进,优先级更高。

2. 协商缓存

协商缓存(Conditional Cache)需要向服务器验证资源是否更新。

Last-Modified / If-Modified-Since
Last-Modified: Wed, 21 Oct 2026 07:28:00 GMT 
// 服务器端实现 app.get('/api/data',(req, res)=>{const lastModified =newDate('2026-01-05').toUTCString();const ifModifiedSince = req.get('If-Modified-Since');if(ifModifiedSince === lastModified){return res.status(304).end();// 未修改} res.set('Last-Modified', lastModified); res.json({data:'some data'});});
ETag / If-None-Match
ETag: "abc123" 
// 服务器端实现const crypto =require('crypto'); app.get('/api/data',(req, res)=>{const data =JSON.stringify({data:'some data'});const etag = crypto.createHash('md5').update(data).digest('hex');const ifNoneMatch = req.get('If-None-Match');if(ifNoneMatch === etag){return res.status(304).end();} res.set('ETag', etag); res.json(JSON.parse(data));});

ETag vs Last-Modified

特性ETagLast-Modified
精度基于内容哈希基于时间戳
准确性更高可能不准确(秒级)
优先级更高较低
支持度现代浏览器广泛支持所有浏览器支持

3. 缓存控制指令

常用指令组合
// 不缓存 res.set('Cache-Control','no-store, no-cache, must-revalidate');// 短时间缓存 res.set('Cache-Control','public, max-age=300');// 5分钟// 长时间缓存(静态资源) res.set('Cache-Control','public, max-age=31536000, immutable');// 私有缓存(敏感数据) res.set('Cache-Control','private, max-age=3600');// 代理缓存 res.set('Cache-Control','public, s-maxage=3600');
Vary 头
Vary: Accept-Encoding 
// 根据 Accept-Encoding 缓存不同版本 res.set('Vary','Accept-Encoding, User-Agent');

Service Worker 缓存

Service Worker 是在浏览器后台运行的脚本,提供了强大的缓存控制能力。

1. Cache Storage

// 注册 Service Workerif('serviceWorker'in navigator){ navigator.serviceWorker.register('/sw.js').then(registration=>{ console.log('SW registered:', registration);});}
// sw.js - Service Worker 文件constCACHE_NAME='my-app-v1';const urlsToCache =['/','/static/js/main.js','/static/css/main.css','/api/user-data'];// 安装阶段 - 缓存资源 self.addEventListener('install',event=>{ event.waitUntil( caches.open(CACHE_NAME).then(cache=>{ console.log('Opened cache');return cache.addAll(urlsToCache);}));});// 激活阶段 - 清理旧缓存 self.addEventListener('activate',event=>{ event.waitUntil( caches.keys().then(cacheNames=>{return Promise.all( cacheNames.map(cacheName=>{if(cacheName !==CACHE_NAME){return caches.delete(cacheName);}}));}));});// 拦截请求 self.addEventListener('fetch',event=>{ event.respondWith( caches.match(event.request).then(response=>{// 如果缓存中有,直接返回if(response){return response;}// 否则请求网络returnfetch(event.request);}));});

2. 缓存策略

Cache First(缓存优先)
self.addEventListener('fetch',event=>{// 只缓存 GET 请求if(event.request.method !=='GET')return; event.respondWith( caches.match(event.request).then(cachedResponse=>{if(cachedResponse){return cachedResponse;}returnfetch(event.request).then(response=>{// 检查响应是否有效if(!response || response.status !==200|| response.type !=='basic'){return response;}// 克隆响应并缓存const responseToCache = response.clone(); caches.open(CACHE_NAME).then(cache=>{ cache.put(event.request, responseToCache);});return response;});}));});
Network First(网络优先)
self.addEventListener('fetch',event=>{if(event.request.method !=='GET')return; event.respondWith(fetch(event.request).then(response=>{// 网络请求成功,缓存响应const responseClone = response.clone(); caches.open(CACHE_NAME).then(cache=>{ cache.put(event.request, responseClone);});return response;}).catch(()=>{// 网络请求失败,使用缓存return caches.match(event.request);}));});
Stale While Revalidate(过期数据可用,同时后台更新)
self.addEventListener('fetch',event=>{if(event.request.method !=='GET')return; event.respondWith( caches.match(event.request).then(cachedResponse=>{const networkFetch =fetch(event.request).then(response=>{// 更新缓存const responseClone = response.clone(); caches.open(CACHE_NAME).then(cache=>{ cache.put(event.request, responseClone);});return response;}).catch(()=>{// 网络请求失败 console.error('Network fetch failed');});// 立即返回缓存,同时后台更新return cachedResponse || networkFetch;}));});

3. 离线优先

// IndexedDB 辅助类classIDBHelper{constructor(dbName, storeName){this.dbName = dbName;this.storeName = storeName;this.db =null;}asyncinit(){returnnewPromise((resolve, reject)=>{const request = indexedDB.open(this.dbName,1); request.onerror=()=>reject(request.error); request.onsuccess=()=>{this.db = request.result;resolve(this.db);}; request.onupgradeneeded=(event)=>{const db = event.target.result;if(!db.objectStoreNames.contains(this.storeName)){ db.createObjectStore(this.storeName,{keyPath:'id'});}};});}asyncget(key){returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readonly');const store = transaction.objectStore(this.storeName);const request = store.get(key); request.onerror=()=>reject(request.error); request.onsuccess=()=>resolve(request.result);});}asyncset(value){returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readwrite');const store = transaction.objectStore(this.storeName);const request = store.put(value); request.onerror=()=>reject(request.error); request.onsuccess=()=>resolve(request.result);});}}// 使用 IndexedDB 缓存数据const idbHelper =newIDBHelper('MyAppDB','apiCache'); self.addEventListener('fetch',event=>{if(event.request.url.includes('/api/')){ event.respondWith((async()=>{try{// 尝试网络请求const networkResponse =awaitfetch(event.request);// 缓存响应if(networkResponse.ok){await idbHelper.set({id: event.request.url,data:await networkResponse.clone().json(),timestamp: Date.now()});}return networkResponse;}catch(error){// 网络失败,尝试缓存const cached =await idbHelper.get(event.request.url);if(cached){returnnewResponse(JSON.stringify(cached.data),{headers:{'Content-Type':'application/json'}});}// 没有缓存,返回离线页面returnnewResponse('Offline',{status:503});}})());}});

内存缓存

内存缓存是在应用运行期间将数据存储在内存中的缓存方式。

1. 内存数据结构

Map 缓存
classSimpleCache{constructor(){this.cache =newMap();}set(key, value, ttl =0){const expires = ttl >0? Date.now()+ ttl :0;this.cache.set(key,{ value, expires });}get(key){const item =this.cache.get(key);if(!item)returnnull;// 检查是否过期if(item.expires && item.expires < Date.now()){this.cache.delete(key);returnnull;}return item.value;}delete(key){this.cache.delete(key);}clear(){this.cache.clear();}// 获取缓存大小size(){returnthis.cache.size;}// 清理过期项cleanup(){const now = Date.now();for(const[key, item]ofthis.cache.entries()){if(item.expires && item.expires < now){this.cache.delete(key);}}}}// 使用示例const cache =newSimpleCache();// 缓存用户信息,10分钟过期 cache.set('user:123',{name:'张三',age:25},10*60*1000);const user = cache.get('user:123'); console.log(user);// { name: '张三', age: 25 }
WeakMap 缓存
classWeakRefCache{constructor(){this.cache =newWeakMap();this.timeouts =newWeakMap();}set(key, value, ttl =0){this.cache.set(key,{ value,timestamp: Date.now()});if(ttl >0){const timeoutId =setTimeout(()=>{this.delete(key);}, ttl);this.timeouts.set(key, timeoutId);}}get(key){const item =this.cache.get(key);return item ? item.value :null;}delete(key){this.cache.delete(key);const timeoutId =this.timeouts.get(key);if(timeoutId){clearTimeout(timeoutId);this.timeouts.delete(key);}}}// 使用示例const weakCache =newWeakRefCache();// 缓存 DOM 元素相关数据const element = document.querySelector('#myElement'); weakCache.set(element,{data:'some data'},5*60*1000);

2. LRU 缓存实现

classLRUCache{constructor(limit =100){this.limit = limit;this.cache =newMap();}get(key){if(!this.cache.has(key))returnnull;const value =this.cache.get(key).value;// 将访问的项移到末尾(最近使用)this.cache.delete(key);this.cache.set(key,{ value,timestamp: Date.now()});return value;}set(key, value, ttl =0){// 检查是否已存在if(this.cache.has(key)){this.cache.delete(key);}elseif(this.cache.size >=this.limit){// 删除最久未使用的项(第一个)const firstKey =this.cache.keys().next().value;this.cache.delete(firstKey);}const expires = ttl >0? Date.now()+ ttl :0;this.cache.set(key,{ value, expires,timestamp: Date.now()});}has(key){const item =this.cache.get(key);if(!item)returnfalse;if(item.expires && item.expires < Date.now()){this.cache.delete(key);returnfalse;}returntrue;}delete(key){this.cache.delete(key);}clear(){this.cache.clear();}// 获取所有有效项getValidItems(){const now = Date.now();const validItems =[];for(const[key, item]ofthis.cache.entries()){if(!item.expires || item.expires >= now){ validItems.push({ key,value: item.value });}else{this.cache.delete(key);}}return validItems;}}// 使用示例const lruCache =newLRUCache(50);// 缓存 API 响应asyncfunctionfetchWithCache(url, ttl =5*60*1000){if(lruCache.has(url)){ console.log('使用缓存:', url);return lruCache.get(url);}const response =awaitfetch(url);const data =await response.json(); lruCache.set(url, data, ttl);return data;}

3. 内存缓存管理

缓存管理器
classCacheManager{constructor(){this.caches =newMap();this.cleanupInterval =null;}createCache(name, options ={}){const{ limit =100, ttl =0}= options;if(this.caches.has(name)){returnthis.caches.get(name);}const cache =newLRUCache(limit);const cacheWrapper ={ name,set:(key, value)=> cache.set(key, value, ttl),get:(key)=> cache.get(key),has:(key)=> cache.has(key),delete:(key)=> cache.delete(key),clear:()=> cache.clear(),size:()=> cache.cache.size,getStats:()=>({ name,size: cache.cache.size, limit, ttl })};this.caches.set(name, cacheWrapper);return cacheWrapper;}getCache(name){returnthis.caches.get(name);}deleteCache(name){const cache =this.caches.get(name);if(cache){ cache.clear();this.caches.delete(name);}}clearAll(){for(const cache ofthis.caches.values()){ cache.clear();}}getAllStats(){const stats =[];for(const cache ofthis.caches.values()){ stats.push(cache.getStats());}return stats;}// 启动定期清理startCleanup(interval =60000){if(this.cleanupInterval)return;this.cleanupInterval =setInterval(()=>{for(const cache ofthis.caches.values()){const validItems = cache.getValidItems?.();if(validItems){ console.log(`清理缓存 ${cache.name},剩余有效项: ${validItems.length}`);}}}, interval);}stopCleanup(){if(this.cleanupInterval){clearInterval(this.cleanupInterval);this.cleanupInterval =null;}}}// 全局缓存管理器实例const cacheManager =newCacheManager();// 创建不同类型的缓存const apiCache = cacheManager.createCache('api',{limit:200,ttl:300000});const componentCache = cacheManager.createCache('component',{limit:50,ttl:600000});const userCache = cacheManager.createCache('user',{limit:100,ttl:600000});// 启动定期清理 cacheManager.startCleanup();// 在页面卸载时清理 window.addEventListener('beforeunload',()=>{ cacheManager.stopCleanup();});

状态管理缓存

1. Redux 缓存

// 使用 redux-persist 持久化状态import{ persistStore, persistReducer }from'redux-persist';import storage from'redux-persist/lib/storage';import{ configureStore }from'@reduxjs/toolkit';import userReducer from'./userSlice';// 配置持久化const persistConfig ={key:'root', storage,whitelist:['user','settings'],// 只持久化这些 reducerblacklist:['temp']// 不持久化这些 reducer};const persistedReducer =persistReducer(persistConfig, rootReducer);const store =configureStore({reducer: persistedReducer,middleware:(getDefaultMiddleware)=>getDefaultMiddleware({serializableCheck:{ignoredActions:[FLUSH,REHYDRATE,PAUSE,PERSIST,PURGE,REGISTER]}})});const persistor =persistStore(store);// 在组件中使用import{ useSelector }from'react-redux';functionUserProfile(){const user =useSelector((state)=> state.user.data);const isLoading =useSelector((state)=> state.user.loading);if(isLoading)return<div>加载中...</div>;return<div>{user.name}</div>;}
自定义中间件缓存
// API 缓存中间件constapiCacheMiddleware=(store)=>(next)=>(action)=>{const{ type, payload }= action;// 如果是 API 请求if(type.startsWith('api/')){const cacheKey =JSON.stringify(payload);const cachedData =getFromCache(cacheKey);if(cachedData &&!payload.forceRefresh){// 返回缓存数据return{type:`${type}_SUCCESS`,payload: cachedData };}}const result =next(action);// 如果请求成功,缓存结果if(type.endsWith('_SUCCESS')){const{ url, ttl =300000}= payload;setCache(url, action.payload, ttl);}return result;};// 使用缓存中间件const store =configureStore({reducer: rootReducer,middleware:(getDefaultMiddleware)=>getDefaultMiddleware().concat(apiCacheMiddleware)});

2. Vuex/Pinia 缓存

// Pinia 缓存插件exportfunctioncachePlugin({ store }){// 从 localStorage 恢复状态const savedState = localStorage.getItem('pinia-state');if(savedState){ store.$patch(JSON.parse(savedState));}// 状态变化时保存到 localStorage store.$subscribe((mutation, state)=>{ localStorage.setItem('pinia-state',JSON.stringify(state));});}// main.jsimport{ createPinia }from'pinia';import{ cachePlugin }from'./plugins/cache';const pinia =createPinia(); pinia.use(cachePlugin); app.use(pinia);
Pinia 缓存 Store
// stores/cache.jsimport{ defineStore }from'pinia';import axios from'axios';exportconst useCacheStore =defineStore('cache',{state:()=>({_cache:newMap(),_timestamps:newMap()}),actions:{asyncget(key, fetcher, ttl =300000){// 检查缓存是否存在且未过期if(this._cache.has(key)){const timestamp =this._timestamps.get(key);if(Date.now()- timestamp < ttl){returnthis._cache.get(key);}}// 获取新数据const data =awaitfetcher();this._cache.set(key, data);this._timestamps.set(key, Date.now());return data;},set(key, value){this._cache.set(key, value);this._timestamps.set(key, Date.now());},delete(key){this._cache.delete(key);this._timestamps.delete(key);},clear(){this._cache.clear();this._timestamps.clear();}}});// 使用缓存 Storeconst cacheStore =useCacheStore();const userData =await cacheStore.get('user:123',async()=>{const response =await axios.get('/api/user/123');return response.data;});

3. React Query 缓存

// React Query 配置import{ QueryClient, QueryClientProvider }from'@tanstack/react-query';const queryClient =newQueryClient({defaultOptions:{queries:{staleTime:5*60*1000,// 5分钟内数据新鲜cacheTime:10*60*1000,// 10分钟后清理缓存retry:3,refetchOnWindowFocus:false}}});functionApp(){return(<QueryClientProvider client={queryClient}><UserProfile /></QueryClientProvider>);}// 使用 React Queryimport{ useQuery }from'@tanstack/react-query';functionUserProfile({ userId }){const{ data, isLoading, error }=useQuery(['user', userId],async()=>{const response =awaitfetch(`/api/user/${userId}`);if(!response.ok)thrownewError('Network error');return response.json();},{staleTime:5*60*1000,// 缓存5分钟cacheTime:10*60*1000,enabled:!!userId // 只有 userId 存在时才执行查询});if(isLoading)return<div>加载中...</div>;if(error)return<div>错误:{error.message}</div>;return<div>{data.name}</div>;}// 手动操作缓存functionupdateUser(){ queryClient.setQueryData(['user', userId],(oldData)=>({...oldData,name:'新名称'}));// 失效缓存 queryClient.invalidateQueries(['user']);}

浏览器存储缓存

1. LocalStorage

// LocalStorage 封装类classLocalStorageCache{constructor(prefix ='cache_'){this.prefix = prefix;}set(key, value, ttl =0){const data ={ value,timestamp: Date.now(),ttl: ttl >0? ttl :null}; localStorage.setItem(this.prefix + key,JSON.stringify(data));}get(key){const item = localStorage.getItem(this.prefix + key);if(!item)returnnull;try{const data =JSON.parse(item);// 检查是否过期if(data.ttl && Date.now()- data.timestamp > data.ttl){this.delete(key);returnnull;}return data.value;}catch(error){ console.error('Parse error:', error);this.delete(key);returnnull;}}delete(key){ localStorage.removeItem(this.prefix + key);}clear(){const keys = Object.keys(localStorage); keys.forEach(key=>{if(key.startsWith(this.prefix)){ localStorage.removeItem(key);}});}// 获取所有缓存键getAllKeys(){return Object.keys(localStorage).filter(key=> key.startsWith(this.prefix)).map(key=> key.replace(this.prefix,''));}}// 使用示例const localCache =newLocalStorageCache();// 缓存用户设置 localCache.set('userSettings',{theme:'dark',language:'zh-CN'},24*60*60*1000);// 24小时const settings = localCache.get('userSettings'); console.log(settings);// { theme: 'dark', language: 'zh-CN' }

2. SessionStorage

// SessionStorage 缓存classSessionStorageCache{constructor(prefix ='session_'){this.prefix = prefix;}set(key, value){const data ={ value,timestamp: Date.now()}; sessionStorage.setItem(this.prefix + key,JSON.stringify(data));}get(key){const item = sessionStorage.getItem(this.prefix + key);if(!item)returnnull;try{const data =JSON.parse(item);return data.value;}catch(error){ console.error('Parse error:', error);this.delete(key);returnnull;}}delete(key){ sessionStorage.removeItem(this.prefix + key);}clear(){const keys = Object.keys(sessionStorage); keys.forEach(key=>{if(key.startsWith(this.prefix)){ sessionStorage.removeItem(key);}});}}// 使用示例const sessionCache =newSessionStorageCache();// 缓存表单数据 sessionCache.set('formData',{name:'张三',email:'[email protected]'});// 页面刷新后数据仍然存在(会话期间)const formData = sessionCache.get('formData');

3. IndexedDB

// IndexedDB 封装classIndexedDBCache{constructor(dbName, storeName){this.dbName = dbName;this.storeName = storeName;this.db =null;}asyncinit(){returnnewPromise((resolve, reject)=>{const request = indexedDB.open(this.dbName,1); request.onerror=()=>reject(request.error); request.onsuccess=()=>{this.db = request.result;resolve(this.db);}; request.onupgradeneeded=(event)=>{const db = event.target.result;if(!db.objectStoreNames.contains(this.storeName)){const store = db.createObjectStore(this.storeName,{keyPath:'key'}); store.createIndex('timestamp','timestamp',{unique:false});}};});}asyncset(key, value, ttl =0){const data ={ key, value,timestamp: Date.now(), ttl };returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readwrite');const store = transaction.objectStore(this.storeName);const request = store.put(data); request.onerror=()=>reject(request.error); request.onsuccess=()=>resolve(request.result);});}asyncget(key){returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readonly');const store = transaction.objectStore(this.storeName);const request = store.get(key); request.onerror=()=>reject(request.error); request.onsuccess=()=>{const data = request.result;if(!data){resolve(null);return;}// 检查是否过期if(data.ttl && Date.now()- data.timestamp > data.ttl){this.delete(key);resolve(null);return;}resolve(data.value);};});}asyncdelete(key){returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readwrite');const store = transaction.objectStore(this.storeName);const request = store.delete(key); request.onerror=()=>reject(request.error); request.onsuccess=()=>resolve(request.result);});}asyncclear(){returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readwrite');const store = transaction.objectStore(this.storeName);const request = store.clear(); request.onerror=()=>reject(request.error); request.onsuccess=()=>resolve(request.result);});}asyncgetAll(){returnnewPromise((resolve, reject)=>{const transaction =this.db.transaction([this.storeName],'readonly');const store = transaction.objectStore(this.storeName);const request = store.getAll(); request.onerror=()=>reject(request.error); request.onsuccess=()=>resolve(request.result);});}}// 使用示例const idbCache =newIndexedDBCache('MyApp','apiCache');await idbCache.init();// 缓存大量数据await idbCache.set('user:123',{profile:{name:'张三',age:25},posts:[...],// 大数组preferences:{...}},3600000);// 1小时const userData =await idbCache.get('user:123');

缓存策略详解

1. Cache First

// Cache First 策略:先查缓存,缓存没有再请求网络asyncfunctioncacheFirst(request, cacheName){const cache =await caches.open(cacheName);const cachedResponse =await cache.match(request);if(cachedResponse){return cachedResponse;}const networkResponse =awaitfetch(request);if(networkResponse.ok){ cache.put(request, networkResponse.clone());}return networkResponse;}// 适用场景:静态资源(CSS、JS、图片)const cssResponse =awaitcacheFirst('/static/css/main.css','assets-cache');

2. Network First

// Network First 策略:先请求网络,失败则使用缓存asyncfunctionnetworkFirst(request, cacheName, timeout =5000){const cache =await caches.open(cacheName);try{// 设置超时const networkPromise =fetch(request);const timeoutPromise =newPromise((resolve, reject)=>{setTimeout(()=>reject(newError('Timeout')), timeout);});const response =await Promise.race([networkPromise, timeoutPromise]);if(response.ok){ cache.put(request, response.clone());}return response;}catch(error){// 网络失败,使用缓存const cachedResponse =await cache.match(request);if(cachedResponse){return cachedResponse;}throw error;}}// 适用场景:API 数据const userData =awaitnetworkFirst('/api/user/123','api-cache');

3. Stale While Revalidate

// Stale While Revalidate 策略:返回缓存,同时后台更新asyncfunctionstaleWhileRevalidate(request, cacheName){const cache =await caches.open(cacheName);const cachedResponse =await cache.match(request);const fetchPromise =fetch(request).then(response=>{if(response.ok){ cache.put(request, response.clone());}return response;}).catch(error=>{ console.error('Fetch failed:', error);returnnull;});// 立即返回缓存,同时后台更新return cachedResponse || fetchPromise;}// 适用场景:新闻文章、博客内容const articles =awaitstaleWhileRevalidate('/api/articles','articles-cache');

4. Cache Only

// Cache Only 策略:只从缓存获取asyncfunctioncacheOnly(request, cacheName){const cache =await caches.open(cacheName);const cachedResponse =await cache.match(request);if(!cachedResponse){thrownewError('No cached response found');}return cachedResponse;}// 适用场景:离线页面const offlinePage =awaitcacheOnly('/offline.html','offline-cache');

5. Network Only

// Network Only 策略:只从网络获取asyncfunctionnetworkOnly(request){returnawaitfetch(request);}// 适用场景:登录、支付等敏感操作const loginResponse =awaitnetworkOnly('/api/login',{method:'POST',body:JSON.stringify(credentials)});

策略选择决策树

需要缓存的资源 | ├─ 静态资源(CSS、JS、图片) → Cache First │ └─ 长期缓存(1年)+ 版本控制 │ ├─ API 数据(用户信息、商品列表) → Network First │ └─ 短期缓存(5分钟)+ 错误回退 │ ├─ 频繁更新的内容(新闻、博客) → Stale While Revalidate │ └─ 显示缓存 + 后台更新 │ ├─ 离线页面 → Cache Only │ └─ 预缓存关键页面 │ └─ 敏感操作(登录、支付) → Network Only └─ 不缓存,确保数据最新 

实际应用场景

1. API 数据缓存

用户信息缓存
classUserCache{constructor(){this.cache =newLRUCache(50);this.apiCache =newLocalStorageCache('user_');}asyncgetUser(userId, forceRefresh =false){const cacheKey =`user:${userId}`;// 强制刷新或内存缓存中没有if(!forceRefresh){const cached =this.cache.get(cacheKey);if(cached){ console.log('从内存缓存获取用户:', userId);return cached;}}// 检查本地存储缓存const localCached =this.apiCache.get(cacheKey);if(localCached &&!forceRefresh){ console.log('从本地存储获取用户:', userId);this.cache.set(cacheKey, localCached);return localCached;}// 请求 APItry{const response =awaitfetch(`/api/user/${userId}`);if(!response.ok)thrownewError('Failed to fetch');const userData =await response.json();// 更新缓存this.cache.set(cacheKey, userData);this.apiCache.set(cacheKey, userData,10*60*1000);// 10分钟return userData;}catch(error){ console.error('Failed to fetch user:', error);// 返回本地缓存(如果有)if(localCached){return localCached;}throw error;}}updateUser(userId, userData){const cacheKey =`user:${userId}`;this.cache.set(cacheKey, userData);this.apiCache.set(cacheKey, userData,10*60*1000);}clearUser(userId){const cacheKey =`user:${userId}`;this.cache.delete(cacheKey);this.apiCache.delete(cacheKey);}}const userCache =newUserCache();// 使用const user =await userCache.getUser('123'); userCache.updateUser('123',{...user,name:'新名称'});
分页数据缓存
classPaginatedCache{constructor(){this.cache =newMap();// key: `${url}:${page}`, value: { data, timestamp }this.cacheTime =5*60*1000;// 5分钟}asyncgetPage(url, page, params ={}){const cacheKey =`${url}:${page}:${JSON.stringify(params)}`;const cached =this.cache.get(cacheKey);if(cached && Date.now()- cached.timestamp <this.cacheTime){return cached.data;}const queryParams =newURLSearchParams({ page,...params });const response =awaitfetch(`${url}?${queryParams}`);if(!response.ok)thrownewError('Failed to fetch');const data =await response.json();this.cache.set(cacheKey,{ data,timestamp: Date.now()});return data;}invalidatePage(url, page){// 删除指定页的缓存for(const key ofthis.cache.keys()){if(key.startsWith(`${url}:${page}:`)){this.cache.delete(key);}}}invalidateUrl(url){// 删除指定 URL 的所有缓存for(const key ofthis.cache.keys()){if(key.startsWith(`${url}:`)){this.cache.delete(key);}}}}const paginatedCache =newPaginatedCache();// 使用const products =await paginatedCache.getPage('/api/products',1,{category:'electronics',sort:'price'});

2. 图片资源缓存

图片预加载
classImageCache{constructor(maxCache =50){this.cache =newMap();// key: url, value: { img, timestamp }this.maxCache = maxCache;}preloadImage(url){returnnewPromise((resolve, reject)=>{// 检查缓存const cached =this.cache.get(url);if(cached){resolve(cached.img);return;}const img =newImage(); img.onload=()=>{// 添加到缓存this.cache.set(url,{ img,timestamp: Date.now()});// 如果缓存超过限制,删除最旧的if(this.cache.size >this.maxCache){const firstKey =this.cache.keys().next().value;this.cache.delete(firstKey);}resolve(img);}; img.onerror = reject; img.src = url;});}getImage(url){const cached =this.cache.get(url);return cached ? cached.img :null;}clear(){this.cache.clear();}}const imageCache =newImageCache();// 预加载图片functionpreloadImages(urls){return Promise.all(urls.map(url=> imageCache.preloadImage(url)));}// 使用preloadImages(['/images/hero.jpg','/images/product1.jpg','/images/product2.jpg']).then(()=>{ console.log('所有图片预加载完成');});
图片懒加载
classLazyImageLoader{constructor(){this.imageCache =newImageCache(100);this.observer =null;this.init();}init(){// Intersection Observer 实现懒加载if('IntersectionObserver'in window){this.observer =newIntersectionObserver((entries)=>{ entries.forEach(entry=>{if(entry.isIntersecting){const img = entry.target;const src = img.dataset.src;this.loadImage(img, src);this.observer.unobserve(img);}});},{rootMargin:'50px'// 提前50px开始加载});}}asyncloadImage(img, src){try{const image =awaitthis.imageCache.preloadImage(src); img.src = image.src; img.classList.remove('lazy');}catch(error){ console.error('Failed to load image:', error); img.classList.add('error');}}observe(img){if(this.observer){this.observer.observe(img);}else{// 降级方案:直接加载const src = img.dataset.src;this.loadImage(img, src);}}}const lazyImageLoader =newLazyImageLoader();// HTML// <img alt="示例">// <img alt="示例">// JavaScript document.querySelectorAll('img.lazy').forEach(img=>{ lazyImageLoader.observe(img);});

3. 页面组件缓存

React 组件缓存
// 使用 React.memo 和 useMemo 缓存组件const ExpensiveComponent = React.memo(({ data, filter })=>{const filteredData =useMemo(()=>{return data.filter(item=> item.category === filter);},[data, filter]);return(<div>{filteredData.map(item=>(<div key={item.id}>{item.name}</div>))}</div>);});// 使用 useCallback 缓存函数functionParentComponent(){const[count, setCount]=useState(0);const handleClick =useCallback(()=>{setCount(prev=> prev +1);},[]);return(<div><button onClick={handleClick}>点击 {count} 次</button><ExpensiveComponent data={expensiveData} filter="active"/></div>);}
动态组件缓存
classComponentCache{constructor(){this.cache =newMap();}asyncloadComponent(importFunc){const modulePath = importFunc.toString();// 检查缓存if(this.cache.has(modulePath)){returnthis.cache.get(modulePath);}// 动态加载组件const module =awaitimportFunc();const Component = module.default;// 缓存组件this.cache.set(modulePath, Component);return Component;}clear(){this.cache.clear();}}const componentCache =newComponentCache();// 动态加载路由组件const routes =[{path:'/user',component:()=>import('./UserComponent')},{path:'/product',component:()=>import('./ProductComponent')}];// 渲染路由functionrenderRoute(route){ componentCache.loadComponent(route.component).then(Component=>{ ReactDOM.render(<Component />, document.getElementById('root'));});}

性能优化实践

1. 缓存分层策略

// 多层缓存架构classMultiLayerCache{constructor(){this.l1Cache =newMap();// 内存缓存,最快this.l2Cache =newLocalStorageCache('l2_');// 本地存储this.l3Cache =newIndexedDBCache('MyApp','l3');// IndexedDB}asyncget(key){// L1 缓存if(this.l1Cache.has(key)){returnthis.l1Cache.get(key);}// L2 缓存const l2Data =this.l2Cache.get(key);if(l2Data){this.l1Cache.set(key, l2Data);return l2Data;}// L3 缓存const l3Data =awaitthis.l3Cache.get(key);if(l3Data){this.l1Cache.set(key, l3Data);this.l2Cache.set(key, l3Data);return l3Data;}returnnull;}asyncset(key, value, ttl =0){// 设置所有层级this.l1Cache.set(key, value);this.l2Cache.set(key, value, ttl);awaitthis.l3Cache.set(key, value, ttl);}asyncdelete(key){this.l1Cache.delete(key);this.l2Cache.delete(key);awaitthis.l3Cache.delete(key);}clear(){this.l1Cache.clear();this.l2Cache.clear();this.l3Cache.clear();}}const multiLayerCache =newMultiLayerCache();

2. 缓存预热

// 缓存预热classCacheWarmer{constructor(cache){this.cache = cache;}asyncwarmUp(config){ console.log('开始缓存预热...');const promises = config.map(async({ key, fetcher, ttl })=>{try{const data =awaitfetcher();awaitthis.cache.set(key, data, ttl); console.log(`预热成功: ${key}`);}catch(error){ console.error(`预热失败: ${key}`, error);}});await Promise.all(promises); console.log('缓存预热完成');}}// 配置预热数据const warmer =newCacheWarmer(multiLayerCache); warmer.warmUp([{key:'user:123',fetcher:()=>fetch('/api/user/123').then(r=> r.json()),ttl:10*60*1000},{key:'menu-items',fetcher:()=>fetch('/api/menu').then(r=> r.json()),ttl:30*60*1000},{key:'config',fetcher:()=>fetch('/api/config').then(r=> r.json()),ttl:60*60*1000}]);

3. 缓存压缩

// 缓存数据压缩import LZString from'lz-string';classCompressedCache{constructor(cache){this.cache = cache;}asyncset(key, value, ttl =0){// 压缩数据const compressed = LZString.compress(JSON.stringify(value));awaitthis.cache.set(key, compressed, ttl);}asyncget(key){const compressed =awaitthis.cache.get(key);if(!compressed)returnnull;try{const decompressed = LZString.decompress(compressed);returnJSON.parse(decompressed);}catch(error){ console.error('Failed to decompress:', error);returnnull;}}}const compressedCache =newCompressedCache(multiLayerCache);

4. 缓存统计

// 缓存统计classCacheStats{constructor(){this.hits =0;this.misses =0;this.size =0;}recordHit(){this.hits++;}recordMiss(){this.misses++;}gethitRate(){const total =this.hits +this.misses;return total >0?(this.hits / total)*100:0;}getStats(){const total =this.hits +this.misses;return{hits:this.hits,misses:this.misses, total,hitRate:this.hitRate.toFixed(2)+'%',size:this.size };}reset(){this.hits =0;this.misses =0;}}// 带统计的缓存classStatsCache{constructor(cache){this.cache = cache;this.stats =newCacheStats();}asyncget(key){const value =awaitthis.cache.get(key);if(value){this.stats.recordHit();}else{this.stats.recordMiss();}return value;}asyncset(key, value, ttl){returnthis.cache.set(key, value, ttl);}getStats(){returnthis.stats.getStats();}resetStats(){this.stats.reset();}}const statsCache =newStatsCache(multiLayerCache);// 定期输出统计信息setInterval(()=>{ console.log('缓存统计:', statsCache.getStats());},60000);

缓存失效与更新

1. TTL(Time To Live)

// TTL 管理classTTLCache{constructor(){this.cache =newMap();this.timeouts =newMap();}set(key, value, ttl){// 设置缓存this.cache.set(key, value);// 清除之前的定时器if(this.timeouts.has(key)){clearTimeout(this.timeouts.get(key));}// 设置新的定时器if(ttl >0){const timeoutId =setTimeout(()=>{this.delete(key);}, ttl);this.timeouts.set(key, timeoutId);}}get(key){returnthis.cache.get(key);}delete(key){this.cache.delete(key);const timeoutId =this.timeouts.get(key);if(timeoutId){clearTimeout(timeoutId);this.timeouts.delete(key);}}clear(){// 清除所有定时器for(const timeoutId ofthis.timeouts.values()){clearTimeout(timeoutId);}this.timeouts.clear();this.cache.clear();}}

2. 版本控制

// 基于版本的缓存失效classVersionedCache{constructor(){this.cache =newMap();this.version ='v1';}setVersion(newVersion){if(this.version !== newVersion){this.version = newVersion;this.clear();// 版本变化时清除所有缓存}}set(key, value, ttl =0){const versionedKey =`${this.version}:${key}`;this.cache.set(versionedKey,{ value, ttl,timestamp: Date.now()});}get(key){const versionedKey =`${this.version}:${key}`;const item =this.cache.get(versionedKey);if(!item)returnnull;if(item.ttl && Date.now()- item.timestamp > item.ttl){this.delete(key);returnnull;}return item.value;}delete(key){const versionedKey =`${this.version}:${key}`;this.cache.delete(versionedKey);}clear(){this.cache.clear();}}// 使用版本控制const versionedCache =newVersionedCache();// 应用更新时升级版本 versionedCache.setVersion('v2');

3. 基于依赖的失效

// 基于依赖图的缓存失效classDependencyCache{constructor(){this.cache =newMap();this.dependents =newMap();// key -> Set<dependent keys>}set(key, value, dependencies =[]){// 设置缓存this.cache.set(key, value);// 更新依赖关系 dependencies.forEach(dep=>{if(!this.dependents.has(dep)){this.dependents.set(dep,newSet());}this.dependents.get(dep).add(key);});}invalidate(key){// 删除缓存this.cache.delete(key);// 删除依赖它的缓存const deps =this.dependents.get(key);if(deps){ deps.forEach(depKey=>{this.cache.delete(depKey);});this.dependents.delete(key);}}get(key){returnthis.cache.get(key);}}// 使用示例const depCache =newDependencyCache();// 设置缓存和依赖关系 depCache.set('user:123',{name:'张三'},['settings:123']); depCache.set('settings:123',{theme:'dark'});// settings 变化时,user:123 也会失效 depCache.invalidate('settings:123');

4. 手动失效

// 手动失效策略classCacheInvalidator{constructor(){this.patterns =newMap();// pattern -> handler}// 注册失效模式register(pattern, handler){this.patterns.set(pattern, handler);}// 失效缓存asyncinvalidate(cacheKey){for(const[pattern, handler]ofthis.patterns.entries()){if(this.matchPattern(pattern, cacheKey)){awaithandler(cacheKey);}}}matchPattern(pattern, key){// 简单的 glob 模式匹配const regex =newRegExp(pattern.replace('*','.*'));return regex.test(key);}}// 配置失效规则const invalidator =newCacheInvalidator(); invalidator.register('user:*',(key)=>{ console.log('失效用户缓存:', key); cache.delete(key);}); invalidator.register('product:*',(key)=>{ console.log('失效商品缓存:', key); cache.delete(key);});// 使用await invalidator.invalidate('user:123');

常见问题与解决方案

1. 缓存穿透

// 问题:请求不存在的数据,导致缓存失效// 解决:缓存空值或使用布隆过滤器classAntiPenetrationCache{constructor(cache){this.cache = cache;this.nullCache =newSet();// 缓存空值的 keythis.nullTTL =5*60*1000;// 空值缓存5分钟}asyncget(key){// 检查是否是已知不存在的 keyif(this.nullCache.has(key)){returnnull;}const value =awaitthis.cache.get(key);// 如果数据不存在,缓存空值if(value ===null){this.nullCache.add(key);setTimeout(()=>{this.nullCache.delete(key);},this.nullTTL);}return value;}asyncset(key, value){if(value ===null){this.nullCache.add(key);}else{this.nullCache.delete(key);}awaitthis.cache.set(key, value);}}

2. 缓存雪崩

// 问题:大量缓存同时失效// 解决:添加随机延迟、使用分布式锁classAvalancheProtectionCache{constructor(cache){this.cache = cache;this.locks =newSet();}asyncget(key, fetcher, ttl =300000){const value =awaitthis.cache.get(key);if(value !==null){return value;}// 检查是否已经有其他请求在加载if(this.locks.has(key)){// 等待其他请求完成returnnewPromise((resolve)=>{const checkLock =setInterval(()=>{if(!this.locks.has(key)){clearInterval(checkLock);this.get(key, fetcher, ttl).then(resolve);}},100);});}// 获取分布式锁this.locks.add(key);try{const data =awaitfetcher();// 添加随机 TTL 避免同时失效const randomTTL = ttl + Math.random()* ttl *0.1;// 最多额外10%awaitthis.cache.set(key, data, randomTTL);return data;}finally{this.locks.delete(key);}}}

3. 缓存击穿

// 问题:热点数据失效时大量请求直达数据库// 解决:互斥锁classCacheBreakdownProtection{constructor(cache){this.cache = cache;this.locks =newMap();}asyncget(key, fetcher, ttl =300000){let value =awaitthis.cache.get(key);if(value !==null){return value;}// 获取锁(使用分布式锁更好)const lockKey =`lock:${key}`;const lockValue = Date.now().toString();if(this.locks.has(lockKey)){// 等待锁释放returnnewPromise((resolve, reject)=>{const timeout =setTimeout(()=>{this.locks.delete(lockKey);reject(newError('Lock timeout'));},5000);const checkLock =setInterval(()=>{if(!this.locks.has(lockKey)){clearInterval(checkLock);clearTimeout(timeout);this.get(key, fetcher, ttl).then(resolve).catch(reject);}},100);});}// 加锁this.locks.set(lockKey, lockValue);try{const data =awaitfetcher();awaitthis.cache.set(key, data, ttl);return data;}finally{// 释放锁this.locks.delete(lockKey);}}}

4. 数据一致性

// 数据一致性保证classConsistentCache{constructor(cache){this.cache = cache;this.versionMap =newMap();// key -> version}asyncset(key, value, ttl =0){const version = Date.now();const data ={ value, version };awaitthis.cache.set(key, data, ttl);this.versionMap.set(key, version);}asyncget(key){const data =awaitthis.cache.get(key);if(!data)returnnull;// 检查版本是否是最新的const currentVersion =this.versionMap.get(key);if(data.version !== currentVersion){returnnull;// 版本过期}return data.value;}// 标记数据为已更新invalidate(key){this.versionMap.set(key, Date.now());}}

最佳实践

1. 缓存设计原则

// 缓存设计检查清单constCACHE_CHECKLIST={// 1. 明确缓存对象identifyCacheTargets:()=>{// - 静态资源(CSS、JS、图片)// - API 数据(用户信息、列表数据)// - 计算结果(复杂计算、排序、筛选)// - 页面组件(React/Vue 组件)},// 2. 选择合适策略selectStrategy:()=>{// - 静态资源:Cache First// - 频繁更新:Network First// - 展示优先:Stale While Revalidate// - 敏感数据:Network Only},// 3. 设置合理 TTLsetTTL:()=>{// - 用户信息:5-10分钟// - 静态资源:1年// - 配置数据:1小时// - 列表数据:1-5分钟},// 4. 缓存失效策略invalidationStrategy:()=>{// - 基于时间的失效// - 基于版本的失效// - 基于事件的失效// - 手动失效},// 5. 监控和统计monitoring:()=>{// - 命中率统计// - 缓存大小监控// - 性能指标// - 错误率统计}};

2. 缓存最佳实践

// 缓存实践指南classCacheBestPractices{// 1. 缓存键命名规范staticgenerateCacheKey(base, params){return`${base}:${JSON.stringify(params)}`;}// 2. 缓存数据大小限制staticisCacheableSize(size, maxSize =1024*1024){return size <= maxSize;}// 3. 压缩大数据staticasynccompress(data){if(typeof data ==='string'){return LZString.compress(data);}returnJSON.stringify(data);}// 4. 批量操作优化staticasyncbatchGet(cache, keys){const promises = keys.map(key=> cache.get(key));return Promise.all(promises);}staticasyncbatchSet(cache, items){const promises = items.map(({ key, value, ttl })=> cache.set(key, value, ttl));return Promise.all(promises);}// 5. 预加载常用数据staticasyncpreload(cache, configs){const promises = configs.map(({ key, fetcher, ttl })=> cache.get(key).then(value=>{if(value)return value;returnfetcher().then(data=>{ cache.set(key, data, ttl);return data;});}));return Promise.all(promises);}}

3. 性能优化技巧

// 性能优化技巧classCachePerformanceOptimization{// 1. 异步缓存staticasyncasyncCache(cache, key, fetcher, ttl){const cached = cache.get(key);if(cached)return cached;// 启动后台加载fetcher().then(data=>{ cache.set(key, data, ttl);}).catch(error=>{ console.error('Async cache load failed:', error);});// 返回占位数据或 nullreturnnull;}// 2. 缓存预取staticprefetch(cache, urls){ urls.forEach(url=>{// 空闲时预取if('requestIdleCallback'in window){requestIdleCallback(()=>{ cache.get(url);});}else{setTimeout(()=> cache.get(url),0);}});}// 3. 缓存分片staticshardCache(cache, shardCount =10){const shardedCaches = Array.from({length: shardCount },()=>newMap());return{get(key){const shardIndex =this.getShardIndex(key);return shardedCaches[shardIndex].get(key);},set(key, value, ttl){const shardIndex =this.getShardIndex(key); shardedCaches[shardIndex].set(key, value);},getShardIndex(key){let hash =0;for(let i =0; i < key.length; i++){ hash =(hash <<5)- hash + key.charCodeAt(i); hash |=0;}return Math.abs(hash)% shardCount;}};}// 4. 缓存统计和优化建议staticanalyzeCache(cache){const stats = cache.getStats();const suggestions =[];if(stats.hitRate <0.8){ suggestions.push('命中率低于80%,建议调整缓存策略');}if(stats.size >100){ suggestions.push('缓存项过多,考虑使用 LRU 策略');}return{ stats, suggestions };}}

4. 安全性考虑

// 缓存安全classSecureCache{constructor(cache){this.cache = cache;}// 1. 加密敏感数据asyncsetSecure(key, value, password, ttl =0){const encrypted =awaitthis.encrypt(value, password);awaitthis.cache.set(key, encrypted, ttl);}asyncgetSecure(key, password){const encrypted =awaitthis.cache.get(key);if(!encrypted)returnnull;returnawaitthis.decrypt(encrypted, password);}asyncencrypt(data, password){// 使用 Web Crypto API 加密const encoder =newTextEncoder();const dataBuffer = encoder.encode(JSON.stringify(data));const passwordBuffer = encoder.encode(password);// 导入密钥const key =await crypto.subtle.importKey('raw', passwordBuffer,{name:'PBKDF2'},false,['deriveKey']);// 生成盐const salt = crypto.getRandomValues(newUint8Array(16));// 派生密钥const derivedKey =await crypto.subtle.deriveKey({name:'PBKDF2',salt: salt,iterations:100000,hash:'SHA-256'}, key,{name:'AES-GCM',length:256},false,['encrypt']);// 加密数据const iv = crypto.getRandomValues(newUint8Array(12));const encryptedBuffer =await crypto.subtle.encrypt({name:'AES-GCM',iv: iv }, derivedKey, dataBuffer );// 返回加密后的数据(包含盐和 IV)return{salt: Array.from(salt),iv: Array.from(iv),data: Array.from(newUint8Array(encryptedBuffer))};}asyncdecrypt(encryptedData, password){// 解密实现const{ salt, iv, data }= encryptedData;// ... 解密逻辑returnJSON.parse(decryptedString);}// 2. 防止缓存投毒validateCacheData(data){// 验证数据结构if(typeof data !=='object'|| data ===null){returnfalse;}// 检查敏感字段if(data.password || data.token || data.secret){ console.warn('Sensitive data in cache');returnfalse;}returntrue;}// 3. 访问控制asyncgetWithAccessCheck(key, accessToken){// 验证访问令牌if(!this.validateAccessToken(accessToken)){thrownewError('Access denied');}const data =awaitthis.cache.get(key);if(!this.validateCacheData(data)){thrownewError('Invalid cache data');}return data;}}

总结

缓存技术总结

缓存是前端性能优化的核心技术之一,它通过在多个层级存储数据副本来提高访问速度和减少网络请求。

主要缓存技术
  1. HTTP 缓存:浏览器层面的缓存,控制静态资源的缓存行为
  2. Service Worker 缓存:强大的缓存控制能力,支持离线应用
  3. 内存缓存:最快的缓存方式,适用于临时数据
  4. 状态管理缓存:应用层面的数据缓存,提升用户体验
  5. 浏览器存储缓存:本地持久化存储,跨会话数据共享
关键策略
  • Cache First:适用于静态资源
  • Network First:适用于频繁更新的数据
  • Stale While Revalidate:平衡性能和新鲜度
  • Cache Only:适用于离线页面
  • Network Only:适用于敏感数据
最佳实践
  1. 合理选择缓存层级:多层缓存架构
  2. 设置合适的 TTL:根据数据特性调整过期时间
  3. 监控缓存性能:跟踪命中率和性能指标
  4. 处理缓存问题:防止穿透、雪崩、击穿
  5. 保障数据安全:加密敏感数据,验证缓存内容

Read more

2026年03月14日全球AI前沿动态

2026年03月14日全球AI前沿动态

一句话总结 2026年3月13日前后,全球科技企业在AI大模型、智能体、硬件基础设施、跨行业应用等领域密集发布新品与技术突破,涵盖模型优化、智能体部署、硬件升级、落地场景拓展等多维度,同步伴随投资并购、政策监管、人才流动及伦理安全争议等行业动态。 一、模型与技术突破 1.1 通用大模型(大语言模型与多模态模型) * 英伟达:发布开源模型Nemotron 3 Super,120B参数,混合Mamba-Transformer架构,原生支持100万token上下文,PinchBench得分85.6%(开源榜首);采用NVFP4格式预训练,适配Blackwell架构,B200芯片推理速度达H100的4倍,吞吐量超上代5倍。 * xAI:发布Grok4.20,非幻觉率78%(创行业纪录),智能指数48分(较前代+6分),每百万令牌成本2-6美元;支持事实可靠推理,适用于严谨行业场景。 * 谷歌:发布Gemini Embedding 2,首个原生多模态嵌入模型,可将文本、

Qwen-Image-Edit-2511-Multiple-Angles LoRA:多角度AI图像生成完全指南

Qwen-Image-Edit-2511-Multiple-Angles LoRA:多角度AI图像生成完全指南

引言:AI图像编辑中的相机控制革命 想象一下,你拥有一个虚拟摄影师,能够围绕任何物体旋转,从戏剧性的低角度拍摄调整到俯瞰全景,在特写和广角之间自由切换——而这一切都不需要重新拍摄任何照片。这不再是科幻小说。Qwen-Image-Edit-2511-Multiple-Angles LoRA 已经彻底改变了创作者处理AI图像生成的方式,提供了前所未有的相机视角控制能力。 这款由 fal.ai 在2025年底发布的突破性 LoRA 适配器,将专业电影摄影技术带入了AI图像编辑领域。每月下载量超过16,000次,在 Hugging Face 上获得441+点赞,它正迅速成为内容创作者、电商企业和数字艺术家的必备工具——无论是需要多角度产品展示还是动态视觉叙事。 这款 LoRA 的特别之处在哪里?与传统图像编辑需要手动操作或多次拍摄不同,Multiple-Angles LoRA 能从单张输入图像生成新的视角。它基于3,000多张高质量高斯溅射渲染图训练,支持96个不同的相机姿态,涵盖4个仰角、8个方位角和3个距离级别。 在这份综合指南中,我们将探索关于 Qwen-Image-Edit

AI实践(5)检索增强(RAG)

AI实践(5)检索增强(RAG)

AI实践(5)检索增强(RAG) Author: Once Day Date: 2026年3月2日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: AI实践成长_Once-Day的博客-ZEEKLOG博客 参考文章:Prompt Engineering GuideDocumentation - Claude API DocsOpenAI for developers检索增强生成 (RAG) | Prompt Engineering GuideBuild a RAG agent with LangChain - Docs by LangChain一文读懂:大模型RAG(检索增强生成)含高级方法2026 年 RAG 技术最新进展与落地实践指南 - 个人文章 - SegmentFault

【OpenAI 把 AI 玩明白了】:自主推理 + 动态知识图谱,这 4 个技术突破要颠覆行业

【OpenAI 把 AI 玩明白了】:自主推理 + 动态知识图谱,这 4 个技术突破要颠覆行业

🎁个人主页:User_芊芊君子 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:AI 文章目录: * 一、OpenAI 发展历程与核心定位 * 二、核心技术架构:从模型迭代到自主推理 * 2.1 双核技术 leadership 与研发架构 * 2.2 关键技术创新点(通俗解读) * (1)长时推理与工具自主使用:让AI像人一样“找帮手” * (2)多模态联合训练与理解(2)多模态联合训练与理解:打破文本、图像、语音的“沟通壁垒” * (3)动态知识图谱重构(3)动态知识图谱重构:让AI拥有“跨学科联想能力” * (4)渐进式安全对齐框架(4)渐进式安全对齐框架:给AI装上“安全防火墙” * 三、