瀏覽器有幾種儲存機制?講一講:Storage for the Web

前言

今天咱們來說一講 Web 存儲有幾種機制,並弄清楚什麼是臨時存儲,什麼是持久存儲。git

你可能不知道的是:咱們日常口中所說的持久存儲 localStorage 不少時候實際上是系統級別的「臨時存儲」。github

正文

IndexedDB

Indexed DB 的操做是異步的,不會阻塞主線程的執行,能夠在 window、web workers、service workers 環境中使用。web

IndexedDB 是基於文件存儲的,API 較爲複雜,包含 v1 v2 的差別,建議經過類庫來使用,好比:Dexie.jschrome

Cache Storage API

Cache Storage API 爲緩存的 Request/Response 對象提供存儲機制,常在 ServiceWorker 中應用。json

異步,不會阻塞主線程的執行,能夠在 window、web workers、service workers 環境中使用。api

SessionStorage

同步,會阻塞主線程的執行。瀏覽器

通常用於儲存臨時性的少許的數據。緩存

SessionStorage 是標籤級別的,跟隨者標籤的生命週期,而且會隨着標籤的銷燬而清空數據。session

沒法在 web workers、service workers 環境中使用。異步

它只能儲存字符串,大小限制大約爲 5MB。

LocalStorage

同步,會阻塞主線程的執行。

沒法在 web workers、service workers 環境中使用。

它只能儲存字符串,大小限制大約爲 5MB。

Cookies

Cookies 有它的用途,但不適用於儲存數據。

Cookie 會在每次 HTTP 請求的時候攜帶在請求頭中,大致積的 Cookies 會顯著增長 HTTP 請求的負擔。

Cookies 讀寫是同步的,只能儲存字符串,而且沒法在 web workers 環境中使用。

File System API

File System API 和 FileWriter API 提供讀取或寫入文件到沙箱中(Sandboxed file system)。

它是異步的,不推薦使用,由於 File System API 只能在 Chromium 內核中使用。

File System Access API

File System Access API 設計用於便捷得讀取和編輯本地文件。

但在讀取或寫入本地文件的時候,須要得到用戶受權,而且受權狀態沒法持久化記錄。

Application Cache

Application Cache 已被棄用,不建議使用。

建議遷移至 service workers 或 Cache API。

Storage 可使用多少磁盤空間?

  • Chrome 容許使用 80% 的硬盤空間,單一的源(域名)可使用 60% 的硬盤空間,能夠經過 StorageManager API 檢測最大的硬盤空間限額,其餘基於 Chromium 內核的瀏覽器有不同的限制,可能會容許使用更多的硬盤空間,查看更多實現 PR #3896
  • Internet Explorer 10(IE 10)及以上,最多能夠儲存 250MB,並在超過 10MB 的時候會提示用戶
  • Firefox 容許使用 50% 的空閒硬盤空間,單個一級域名最多可使用 2GB 硬盤空間,能夠經過 StorageManager API 檢測最大的硬盤空間限額
  • Safari 容許使用 1GB,當達到 1GB 的時候會提示用戶(該數據可能不許確,沒有找到 Safari 官方文檔)

現代瀏覽器大多數已經不會再提示用戶以受權更多的儲存空間了。

如何檢測儲存空間是否可用?

在大多數瀏覽器中,能夠經過 StorageManager API 檢測儲存空間總量與正在使用的量

if (navigator.storage && navigator.storage.estimate) {
  const quota = await navigator.storage.estimate();
  // quota.usage -> Number of bytes used.
  // quota.quota -> Maximum number of bytes available.
  const percentageUsed = (quota.usage / quota.quota) * 100;
  console.log(`You've used ${percentageUsed}% of the available storage.`);
  const remaining = quota.quota - quota.usage;
  console.log(`You can write up to ${remaining} more bytes.`);
}
// quota data
{
  "quota": 299977904946,
  "usage": 27154039,
  "usageDetails": {
    "caches": 26813093,
    "indexedDB": 305864,
    "serviceWorkerRegistrations": 35082
  }
}

注意:

  1. 並非全部瀏覽器都實現了,所以使用以前須要先判斷兼容性
  2. 須要捕獲並處理超過配額限額的錯誤

IndexedDB 超限處理

indexedDB 超限將會執行 onabort 回調,並拋出一個 DOMException 錯誤,須要處理它的 QuotaExceededError 異常。

const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
  const error = event.target.error; // DOMException
  if (error.name == 'QuotaExceededError') {
    // Fallback code goes here
  }
};

Cache API 超限處理

拋出一個 Promise Rejection,QuotaExceededError 錯誤對象,須要處理它的 QuotaExceededError 異常。

try {
  const cache = await caches.open('my-cache');
  await cache.add(new Request('/sample1.jpg'));
} catch (err) {
  if (error.name === 'QuotaExceededError') {
    // Fallback code goes here
  }
}

瀏覽器何時回收存儲空間?

Web Storage 分爲兩種儲存模式,分別是:臨時存儲 Best Effort 和持久存儲 Persistent。

默認狀況下網站數據(包括 IndexedDB, Cache API, LocalStorage 等)都儲存在臨時存儲 Best Effort 中,會在存儲空間不足的時候被瀏覽器清除掉。

各個瀏覽器回收存儲空間的差別:

  • Chrome 當瀏覽器存儲空間不足時,會優先清除最近最少使用的數據,逐個清除,直至再也不超限
  • IE 10+ 不會自動清除數據,但會阻止站點繼續寫入數據
  • Firefox 當磁盤空間充滿時,會優先清除最近最少使用的數據,逐個清除,直至再也不超限
  • Safari(iOS、iPadOS、MacOS) 會自動清除超過 7 天以上的數據,但不會清除「已添加至主屏幕」的網站和「PWA」網站

申請和查看持久存儲 Persistent Storage

申請持久存儲 Persistent Storage:

// Request persistent storage for site
if (navigator.storage && navigator.storage.persist) {
  const isPersisted = await navigator.storage.persist();
  console.log(`Persisted storage granted: ${isPersisted}`);
}

查看持久存儲 Persistent Storage 受權狀態:

// Check if site's storage has been marked as persistent
if (navigator.storage && navigator.storage.persist) {
  const isPersisted = await navigator.storage.persisted();
  console.log(`Persisted storage granted: ${isPersisted}`);
}

各個瀏覽器申請持久存儲 Persistent Storage 的差別:

  • 在 Chrome 55 之後,申請持久存儲只須要知足如下任一條件,便可自動得到持久存儲權限,無需用戶確認:

    • 該站點已添加書籤, 而且用戶的書籤數小於等於5個
    • 站點有很高的"site engagement",經過這個命令能夠查看: chrome://site-engagement/
    • 站點已添加到主屏幕
    • 站點啓用了push通知功能
  • 在 Firefox 中,會提示用戶受權

最後測試並驗證:

  1. 打開 https://baidu.com,打開控制檯輸入 await navigator.storage.persist(),返回 true
  2. 打開 https://wy.guahao.com,打開控制檯輸入 await navigator.storage.persist(),返回 false

參考文獻

相關文章
相關標籤/搜索