快取是將網站資料儲存在快取(儲存位置)中的過程,以便為使用者提供更快的存取,提升用戶體驗,減少網頁加載時間;實現快取的方法可以在伺服器端和客戶端實現,前端的部分主要是客戶端快取技術。
💡 Cache 之前端 vs 後端
前端: 用於優化用戶端性能,提升用戶體驗,減少靜態資源的加載。
後端: 用於優化伺服器性能,減少資源消耗,減少資料庫連線和計算。(後端小白自學 Laravel-第 17 天:緩存 Cache)
存儲位置
瀏覽器在本機上儲存靜態資源(HTML、CSS、JavaScript、圖片),在後續存取中,瀏覽器將繞過伺服器從快取中提供這些資源。
前端的 Cache 通常存儲在用戶的瀏覽器中,透過 HTTP 頭部(如 Cache-Control
)來管理。
流程
Service Worker 是一種在瀏覽器中運行的 JavaScript 代理,可以攔截網絡請求並進行處理。它們常用於實現離線體驗、推送通知和資源緩存等功能。
Cache API 是 Service Worker 中的一部分,它允許開發者緩存請求和響應,透過緩存中提取資源,可以減少網絡請求的數量,從而加快加載速度。
step 1:註冊 Service Worker
在 JavaScript 文件中註冊 Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
});
}
step 2:攔截安裝事件
當 Service Worker 安裝時,緩存所需的資源。
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v1').then((cache) => {
return cache.addAll([
'/index.html',
'/styles.css',
'/script.js',
'/image.png'
]);
})
);
});
step 3:攔截請求
在 fetch 事件中處理網絡請求,從緩存中返回響應,或在緩存未命中的情況下進行網絡請求。
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
在瀏覽器裡有不同的機制可以儲存使用者或網站資料,當然也有些儲存限制,以下是這些機制的介紹。
Cookies
記憶體限制:通常每個 cookie 最多 4KB。
最適合:儲存少量數據,例如使用者首選項或會話令牌。
// 設定 cookie
document.cookie = "sessionId=38afes7a83; expires=Thu
// 讀取 cookies
let cookies = document.cookie.split(';');
let sessionId = cookies.find(cookie => cookie.includes ('sessionId'));
🔔 注意:隨每個 HTTP 請求一起發送,因此如果儲存大量資料可能會影響效能。
LocalStorage
沒有
過期日期,即使關閉並重新開啟瀏覽器,資料仍然存在。const user = {
name: "kuku",
age: null,
email: "[kuku@123.com]"
};
localStorage.setItem("user", JSON.stringify(user));
SessionStorage
// 資料儲存到sessionStorage
sessionStorage.setItem("name", "kuku");
// 從sessionStorage取得已儲存的數據
const name = sessionStorage.getItem("name");
🔔 LocalStorage vs SessionStorage:
這樣有看出差別了嗎?關閉瀏覽器 SessionStorage 存的內容就會遺失,但是 LocalStorage 還在的!
IndexedDB
MDN文件:使用 IndexedDB、Window:indexedDB 属性
參考文章:前端如何緩存大筆資料:IndexedDB 介紹/應用
記憶體限制:可能差異很大,但通常為 50MB 以上,感覺有時後沒有真正的限制,可能取決於使用者的可用磁碟空間。
最適合:複雜的結構化資料儲存,適用於離線應用程式或需要大量客戶端資料管理的應用程式。
語法說明:
功能 | 語法 | 說明 |
---|---|---|
開啟數據庫 | indexedDB.open() |
創建或打開一個數據庫 |
添加數據 | add() |
數據添加到對象存儲區 |
讀取數據 | get() |
根據主鍵讀取數據 |
更新數據 | onupgradeneeded |
當數據庫版本更新時觸發,通常用來創建對象存儲區和索引 |
刪除數據 | delete() |
根據主鍵刪除數據 |
處理事件 | onsuccess 和 onerror |
處理成功和錯誤事件 |
// 打開或創建數據庫
const request = indexedDB.open('myDatabase', 1);
request.onupgradeneeded = function(event) {
const db = event.target.result;
// 創建一個對象存儲區
const objectStore = db.createObjectStore('myObjectStore', { keyPath: 'id' });
objectStore.createIndex('name', 'name', { unique: false });
};
request.onsuccess = function(event) {
const db = event.target.result;
console.log('數據庫打開成功!');
// 添加數據
const transaction = db.transaction(['myObjectStore'], 'readwrite');
const objectStore = transaction.objectStore('myObjectStore');
const data = { id: 1, name: 'Alice' };
const addRequest = objectStore.add(data);
addRequest.onsuccess = function() {
console.log('數據添加成功!');
};
// 讀取數據
const getRequest = objectStore.get(1);
getRequest.onsuccess = function() {
console.log('讀取的數據:', getRequest.result);
};
// 刪除數據
const deleteRequest = objectStore.delete(1);
deleteRequest.onsuccess = function() {
console.log('數據刪除成功!');
};
// 交易結束
transaction.oncomplete = function() {
console.log('所有操作完成!');
};
transaction.onerror = function(event) {
console.error('交易失敗:', event.target.error);
}
WebSQL
建議參考文章:後端小白自學 Laravel - 第 6 天:數據庫操作基礎
IndexedDB 和 Laravel 的數據庫在基本功能上有相似之處,但是還是有些不同啦!這裡只是想表達兩者都支持基本的 CRUD(創建、讀取、更新、刪除)操作,只是透過不同 API 操作 IndexedDB API 和 Eloquent ORM。
而且兩邊也有 transaction
防範機制,也就是寫入的時候萬一出現了異常,交易將會自動回滾,避免異常造成資料庫爆了!
但是...
他們還是有個最大的不同,存放位置!
方法 | IndexedDB | Laravel ORM |
---|---|---|
存放位置 | 數據存儲在用戶的瀏覽器 |
數據存儲在後端伺服器 |
訪問方式 | 用 JavaScript 在瀏覽器中訪問,主要用於網頁應用 | 用 PHP 代碼和後端 API 進行訪問 |
同步 | 數據存儲在用戶的設備上,可能會出現沒辦法及時同步 | 數據集中管理的,與服務器的數據庫同步相對簡單 |