iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Modern Web

前端三分鐘 X Progressive Web App 30 天製造解密系列 第 13

Progressive Web App 用戶端儲存簡介 (13)

  • 分享至 

  • xImage
  •  

什麼是用戶端儲存 (Client-side storage)

對一個 App 來說,為了達到某些目的,將相關資料存在用戶端是相對方便的,舉例來說

  • 個人偏好設定,像是常用功能、顏色主題、字體大小
  • 將前一次操作快取,像是紀錄購物車資料或是線上編輯器在斷線時先暫時將資料保存
  • 不常改變的資料或靜態資源快取
  • 離線操作所需要的檔案

通常用戶端的儲存和伺服器端的儲存會是一起搭配使用的,舉例來說當我們使用影音串流功能時,會從伺服器端下載相關資料到用戶端使用,在過程中 App 也能夠將資料快取起來以便下次使用。

不過在實務上,瀏覽器用戶端的儲存目前有各式解決方案,也都有著各自的限制存在,如果是有大小限制的儲存,就必須注意定時和伺服器端同步去避免資料遺失。

常見用戶端儲存機制介紹

目前常見的用戶端儲存機制如下:

  • Cookies: 每次發 Request 都會一起送出,所以要大小控制要注意
  • Web Storage API
    • SessionStorage: 同步阻塞 (synchronous),上限 5MB,僅存在於 Tab 當次操作,無法被 web workers 或 service workers 使用
    • LocalStorage: 同步阻塞 (synchronous),上限 5MB,無法被 web workers 或 service workers 使用
  • Cache API: 非同步,較適合跟網路請求相關的靜態資源快取
  • IndexedDB API: 非同步,適合儲存程式邏輯相關資料,使用上相對複雜,較推薦使用像是 idb 這類相關套件操作
  • WebSQL: 不建議使用

用戶端儲存限制

一般來說儲存空間的上限如下:

  • Chrome 總共最多可以用到 80% 的硬碟,每個網域最高是 60%
  • IE 系列 10 以後最多 250MB
  • Firefox 硬碟空間的 50%
  • Safari 1GB

在 Chrome、Firefox、Edge 等瀏覽器中可以使用以下的程式碼去估計剩餘空間:

https://caniuse.com/mdn-api_storagemanager

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> 用了多少 bytes
  // quota.quota -> 還剩多少 bytes 可使用
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`${percentageUsed}% 已使用`);
  const remaining = quota.quota - quota.usage;
  console.log(`還可以寫入 ${remaining} bytes`);
}

QuotaExceededError 錯誤處理

  • IndexedDB
const transaction = idb.transaction(["entries"], "readwrite");
transaction.onabort = function (event) {
  const error = event.target.error; // DOMException
  if (error.name == "QuotaExceededError") {
    // 錯誤處理
  }
};
  • Cache API
try {
  const cache = await caches.open("my-cache");
  await cache.add(new Request("/test.jpg"));
} catch (err) {
  if (error.name === "QuotaExceededError") {
    // 錯誤處理
  }
}

儲存淘汰機制 (eviction)

資料在儲存上會分成兩種類別

  • Best Effort: 當瀏覽器空間不足,會開始執行淘汰機制
    • Chromium: 從最少使用的開始,會自動清除資料且不會通知用戶
    • Firefox: 從最少使用的開始,會自動清除資料且不會通知用戶
    • Internet Explorer 10+ 不會清除,但會停止寫入
  • Persistent: 不會被自動清除

LRU policy

當硬碟空間即將用完時,瀏覽器會依據 LRU policy (least recently used) 的規則透過去清除快取檔案。

  1. 目前沒有使用的網頁 (tabs/apps)
  2. 比對最後存取的時間

Persistent Storage

為了避免資料被儲存淘汰機制處理掉,我們能夠通過程式碼去確認、啟用 Persistent Storage。

// 確認目前儲存空間是否套用 Persistent
if (navigator.storage && navigator.storage.persist) {
  const isPersisted = await navigator.storage.persisted();
  console.log(`Persisted storage granted: ${isPersisted}`);
}

// 針對這個站台啟用 Persistent Storage
if (navigator.storage && navigator.storage.persist) {
  const isPersisted = await navigator.storage.persist();
  console.log(`Persisted storage granted: ${isPersisted}`);
}

啟用過後底下的儲存皆會受到保護,但要注意啟用後目前尚沒有透過程式停用的方式。

  • Cache API
  • Cookies
  • DOM Storage (Local Storage)
  • File System API
  • IndexedDB
  • Service workers
  • App Cache (deprecated)
  • WebSQL (deprecated)

上一篇
Progressive Web App 架構模式: App Shell Model 概念說明 (12)
下一篇
Progressive Web App 存取本機檔案: File System Access API (14)
系列文
前端三分鐘 X Progressive Web App 30 天製造解密30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言