前端常見的數(shù)據(jù)緩存方案及其實(shí)現(xiàn)細(xì)節(jié)
前言
前端數(shù)據(jù)緩存機(jī)制是提升應(yīng)用性能、減少網(wǎng)絡(luò)請(qǐng)求、優(yōu)化用戶體驗(yàn)的關(guān)鍵技術(shù)手段。以下是前端常見的數(shù)據(jù)緩存方案及其實(shí)現(xiàn)細(xì)節(jié),涵蓋瀏覽器緩存、本地存儲(chǔ)、內(nèi)存緩存等多種策略:
1. 瀏覽器緩存(HTTP 緩存)
通過 HTTP 協(xié)議頭控制緩存,適用于靜態(tài)資源(如 JS、CSS、圖片)和接口響應(yīng)。
1.1 強(qiáng)緩存
- 原理:瀏覽器直接使用本地緩存,不向服務(wù)器發(fā)送請(qǐng)求。
- 實(shí)現(xiàn)方式:
Cache-Control: max-age=3600 # 資源有效期 1 小時(shí)(優(yōu)先級(jí)高) Expires: Wed, 21 Oct 2024 07:28:00 GMT # 過期時(shí)間(HTTP/1.0)
1.2 協(xié)商緩存
- 原理:瀏覽器攜帶緩存標(biāo)識(shí)詢問服務(wù)器資源是否更新。
- 實(shí)現(xiàn)方式:
# 服務(wù)器返回標(biāo)識(shí) ETag: "33a64df551425fcc55e4d42a148795d9" Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT # 瀏覽器請(qǐng)求時(shí)攜帶標(biāo)識(shí) If-None-Match: "33a64df551425fcc55e4d42a148795d9" If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
2. Web Storage
適用于存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù),容量約 5~10MB,分為 localStorage 和 sessionStorage。
2.1 基本使用
// 存儲(chǔ)數(shù)據(jù)(注意:只能存字符串)
localStorage.setItem('user', JSON.stringify({ name: 'Alice' }));
// 讀取數(shù)據(jù)
const user = JSON.parse(localStorage.getItem('user'));
// 刪除數(shù)據(jù)
localStorage.removeItem('user');
2.2 緩存策略示例
async function fetchWithCache(url, cacheKey, ttl = 3600) {
const cachedData = localStorage.getItem(cacheKey);
if (cachedData) {
const { data, timestamp } = JSON.parse(cachedData);
if (Date.now() - timestamp < ttl * 1000) {
return data; // 返回有效緩存
}
}
const response = await fetch(url);
const newData = await response.json();
localStorage.setItem(cacheKey, JSON.stringify({
data: newData,
timestamp: Date.now()
}));
return newData;
}
3. IndexedDB
適用于存儲(chǔ)大量結(jié)構(gòu)化數(shù)據(jù)(支持索引、事務(wù)),容量可達(dá)數(shù)百 MB。
3.1 基本操作
// 打開數(shù)據(jù)庫
const request = indexedDB.open('myDB', 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const store = db.createObjectStore('apiCache', { keyPath: 'url' });
store.createIndex('timestamp', 'timestamp', { unique: false });
};
// 存儲(chǔ)數(shù)據(jù)
function saveToIndexedDB(url, data) {
const transaction = db.transaction('apiCache', 'readwrite');
const store = transaction.objectStore('apiCache');
store.put({ url, data, timestamp: Date.now() });
}
// 查詢數(shù)據(jù)
async function getFromIndexedDB(url) {
return new Promise((resolve) => {
const transaction = db.transaction('apiCache', 'readonly');
const store = transaction.objectStore('apiCache');
const request = store.get(url);
request.onsuccess = (e) => resolve(e.target.result?.data);
});
}
4. 內(nèi)存緩存
適用于單頁應(yīng)用(SPA)中短期數(shù)據(jù)緩存,隨頁面刷新失效。
4.1 全局變量緩存
const memoryCache = new Map();
async function fetchWithMemoryCache(url) {
if (memoryCache.has(url)) {
return memoryCache.get(url);
}
const response = await fetch(url);
const data = await response.json();
memoryCache.set(url, data);
return data;
}
4.2 LRU 緩存策略
class LRUCache {
constructor(maxSize = 100) {
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);
}
}
5. Service Worker 緩存
實(shí)現(xiàn)離線緩存和網(wǎng)絡(luò)請(qǐng)求攔截,適合 PWA 應(yīng)用。
5.1 緩存接口數(shù)據(jù)
// sw.js
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api/')) {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request).then((response) => {
const clone = response.clone();
caches.open('api-cache-v1').then((cache) => {
cache.put(event.request, clone);
});
return response;
});
})
);
}
});
6. 現(xiàn)代框架緩存方案
6.1 React Query
import { useQuery } from 'react-query';
function UserProfile() {
const { data } = useQuery('userData', () =>
fetch('/api/user').then(res => res.json()), {
staleTime: 5 * 60 * 1000, // 5分鐘緩存有效期
cacheTime: 30 * 60 * 1000 // 30分鐘保留時(shí)間
});
// ...
}
6.2 SWR (Stale-While-Revalidate)
import useSWR from 'swr';
function Profile() {
const { data } = useSWR('/api/user', fetcher, {
revalidateOnFocus: false, // 窗口聚焦時(shí)不刷新
dedupingInterval: 60000 // 60秒內(nèi)相同請(qǐng)求去重
});
// ...
}
7. 緩存策略關(guān)鍵問題處理
7.1 緩存失效
- 時(shí)間戳失效:存儲(chǔ)數(shù)據(jù)時(shí)記錄時(shí)間戳,定期檢查過期
- 版本號(hào)控制:緩存鍵名包含版本號(hào)(如
user-v2) - 主動(dòng)清除:當(dāng)數(shù)據(jù)變更時(shí)觸發(fā)緩存更新
7.2 緩存一致性
- 數(shù)據(jù)更新廣播:通過 WebSocket 或 EventSource 通知前端更新緩存
- 手動(dòng)刷新機(jī)制:提供用戶手動(dòng)刷新按鈕(如
pull-to-refresh)
7.3 敏感數(shù)據(jù)處理
- 避免緩存隱私數(shù)據(jù)(如 token、密碼)
- 使用
sessionStorage替代localStorage存儲(chǔ)會(huì)話數(shù)據(jù)
緩存方案選型建議
| 場景 | 推薦方案 | 容量 | 有效期 |
|---|---|---|---|
| 靜態(tài)資源 | HTTP 強(qiáng)緩存 | 無上限 | 長期 |
| 低頻變動(dòng)的接口數(shù)據(jù) | localStorage | 5~10MB | 自定義 |
| 大量結(jié)構(gòu)化數(shù)據(jù) | IndexedDB | 數(shù)百M(fèi)B | 長期 |
| 實(shí)時(shí)性要求高的數(shù)據(jù) | 內(nèi)存緩存 | 內(nèi)存限制 | 頁面會(huì)話 |
| 離線優(yōu)先應(yīng)用 | Service Worker | 50~250MB | 自定義 |
最佳實(shí)踐
- 分層緩存:結(jié)合 HTTP 緩存 + 內(nèi)存緩存 + 持久化存儲(chǔ)
- 緩存降級(jí):優(yōu)先從內(nèi)存讀取,其次本地存儲(chǔ),最后網(wǎng)絡(luò)請(qǐng)求
- 監(jiān)控指標(biāo):跟蹤緩存命中率、存儲(chǔ)使用量、數(shù)據(jù)新鮮度
- 安全清理:定時(shí)清理過期緩存,避免存儲(chǔ)空間溢出
通過合理設(shè)計(jì)緩存機(jī)制,可顯著提升前端性能,但在實(shí)際應(yīng)用中需平衡以下關(guān)系:
? 新鮮度 vs 性能
? 存儲(chǔ)空間 vs 用戶體驗(yàn)
? 開發(fā)成本 vs 維護(hù)成本
到此這篇關(guān)于前端常見的數(shù)據(jù)緩存方案及其實(shí)現(xiàn)細(xì)節(jié)的文章就介紹到這了,更多相關(guān)前端數(shù)據(jù)緩存機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS查找字符串中出現(xiàn)最多的字符及個(gè)數(shù)統(tǒng)計(jì)
最近在項(xiàng)目中遇到這樣的需求:求字符串'nininihaoa'中出現(xiàn)次數(shù)最多字符。怎么實(shí)現(xiàn)呢?下面小編給大家分享具體實(shí)現(xiàn)代碼,需要的朋友參考下吧2017-02-02
js和jquery實(shí)現(xiàn)監(jiān)聽鍵盤事件示例代碼
這篇文章主要為大家介紹了js實(shí)現(xiàn)監(jiān)聽鍵盤事件示例代碼,監(jiān)聽鍵盤組合鍵CTRL+C,以便做出對(duì)應(yīng)的響應(yīng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01
js substr、substring和slice使用說明小記
關(guān)于substr、substring和slice方法區(qū)別的文章,網(wǎng)上搜到了許多,文章內(nèi)容也基本一致。而后,我將其中一篇文章中的代碼挪到本地進(jìn)行了測試,發(fā)現(xiàn)測試結(jié)果和原文中的有些出入。2011-09-09
js實(shí)現(xiàn)對(duì)table動(dòng)態(tài)添加、刪除和更新的方法
這篇文章主要介紹了js實(shí)現(xiàn)對(duì)table動(dòng)態(tài)添加、刪除和更新的方法,涉及javascript針對(duì)html中table表格節(jié)點(diǎn)的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02
HTML5附件拖拽上傳drop & google.gears實(shí)現(xiàn)代碼
從gmail 的附件拖拽上傳,到網(wǎng)易郵箱的拖拽上傳,我們看到了html 5 為我們帶來了新的web體驗(yàn)。2011-04-04
js實(shí)現(xiàn)旋轉(zhuǎn)木馬輪播圖效果
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)旋轉(zhuǎn)木馬輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01

