browser storage - Lauviah0622/Lavi-Note GitHub Wiki

本文幾乎完全整理 & 翻譯自這篇文章

Browser storage 的使用情境:

  1. 維持 App 的使用狀態,像是 theme,或者是其他個人設定
  2. 為了實用性,性能(可能像是 cache)等等而把資料儲存在 Browser 端
  3. PWA

Browser Storage 的資料有幾種特性

  • 依照不同的儲存方式可能是永久的,或者是暫時的(終止 session 就會清除掉)。
  • OS、瀏覽器、extension、或者是 user 自己都有可能把資料清除。
  • 每個 Origin 只能拿到自己的 Storage。 \

Devtool

可以在 Application(Firefox 是 Storage) 視窗看到 Browser Storage 的資料

檢查 Storage 可不可用的方式

  1. 直接檢查變數有沒有宣告
// is localStorage available?
if (typeof localStorage !== 'undefined') {
  // yes!
}

  1. 設看看
try {
  localStorage.setItem('myObject', myObject);
}
catch (e) {
  console.log('localStorage failed:', e);
}
  1. StorageManager API

StorageManager 是一個異步的 API, IE 還有 Safari 不支援。

.estimate 能夠計算配額還有以使用空間。如果可用,就會回傳 resolve 的 Promise。

計算出來的空間就像 estimate 這個名稱一樣,只是估算。會對 storage 進行壓縮等等的步驟再給數字。

瀏覽器會依照不同的網站受歡迎程度還有訪問頻率來決定說能夠用多少空間。

https://developer.mozilla.org/zh-CN/docs/Web/API/StorageManager/estimate

(async () => {
  // Storage API support
  if (!navigator.storage) return;
  const storage = await navigator.storage.estimate();
  console.log(`permitted: ${ storage.quota / 1024 } Kb`);
  console.log(`used     : ${ storage.usage / 1024 } Kb`);
  console.log(`% used   : ${ Math.round((storage.usage / storage.quota) * 100) }%`);
  console.log(`remaining: ${ Math.floor((storage.quota - storage.usage) / 1024) } Kb`);
})();

quota:該 Origin 的可使用空間 usage:已使用空間

但是 Storage API 計算的是哪些儲存方式的空間?

現行可用的儲存方式

Variables

對,JS 的變數也可以算是其中一種

使用情境:

  • 暫時性的資料,如果要永久保存,需要在頁面 unload 的時候寫入其他儲存方式

優點:

  • 最快,而且只要寫 JS 就可以用
  • 不用序列化(也就是不用轉成 JSON)

缺點:

  • 暫時性的儲存方式
  • 如果是全域變數,第三方的 JS 可以改寫

DOM Storage

簡單說,就是把存在資料存在 HTML element 的 Attribute 裡面。

能夠使用的方法:

  • setAttributegetAttribute
  • dataset
  • classList API,也就是說很適合拿來作為 boolean 屬性

使用情境:

  • 儲存和 DOM 狀態相關的資料蠻有用的
  • 如果想要從 server 就傳遞狀態可以這樣使用。
    例如:從 CMS 想要塞一些狀態或者值在裡面就蠻適合這樣的方式

優點:

  • 從 client 和 Server 都可以設定 State!
  • 如果不用頻繁的 DOM search 或改變 render 的 layout,其實蠻快速的

缺點:

  • refresh 就會不見
  • 第三方 script 能夠操作你的值
  • 只能 attribute 只能存 string,就代表著需要序列化

Web Storage

分兩種

  • Local Storage:儲存永久性的資料
  • Session Storage:儲存暫時性的資料

特性

  • 儲存還有讀取都是同步的,所以可能會 block 到 main thread
  • Local storage 以 domain 為單位儲存,故可以跨分頁。session storage 以 session 為單位儲存。瀏覽器在開啟一個分頁會建立一個 session,故為各分頁專屬,並在關閉 tab 會終止 session。
  • 單一 domain 所有 localStorage Items 的上限是 5MB,單一筆的上限才是 2.6MB(在 Webkit-based 瀏覽器中)

儲存空間的大小依照不同的 User Agent 實做,Chrome 為 5mb,在 opera 還有 firefox 中,則可以自行設定。

這個數字也可能依不同的版本而有所改變。可看這篇,裡面提到 chrome 26 只有 2600kb,但在採用 chromium 92 的 Brave 1.28 (目前使用的瀏覽器)有 5300kb

關於 webstorage 最大 size 的 stack-overflow 問答:https://stackoverflow.com/questions/2989284/what-is-the-max-size-of-localstorage-values

可以用這個網站來檢查能儲存多少字元

API:

  • Storage.setItem(key, value):
  • Storage.getItem(key):拿 key 的值
  • Storage.removeItem(key):移除 key
  • Storage.key(number):回傳第 n 個 key
  • Storage.length:回傳儲存的 key value 數量
  • Storage.clear():清空所有 Storage

WebStorage event:

window.addEventListener('storage', e => {
  console.log(`key changed: ${ e.key }`);
  console.log(`from       : ${ e.oldValue }`);
  console.log(`to         : ${ e.newValue }`);
});

使用情境:

  • 比較不常操作的值
  • 比較簡單的值

優點:

  • 簡單的 API
  • 瀏覽器的支援度良好

缺點:

  • 只能儲存 String,所以需要序列化
  • 因為是同步儲存,存大量的資料可能會影響頁面性能
  • key value 的方式可能會覆蓋到其他 component 的 name

IndexedDB

一個不出世的神兵利器

特性

  • NoSQL 的 key-value 資料庫
  • 基本上是非同步,但在 webWorker 能夠使用同步的 API
  • transaction
  • 能夠 search
  • 能夠使用 index 做查找(還不清楚這是什麼,優是在哪裡)
  • 至少可以使用 1GB,甚至可以到儲存空間的 60%
  • 能夠儲存未序列化的資料

使用情境:

  • 你要儲存大量的的資料
  • 需要良好的性能
  • 這邊補一個猜測,在 PWA 上,這應該是非常好的儲存方式。

優點:

  • 能夠儲存未序列化的資料
  • 非常適合儲存大量的數據
  • 瀏覽器支援良好

缺點:

  • API 非常的糟,非常難用

推薦使用其他包裝好的,更易用的 library:

  • idb
  • zangoDB:類似 mongoDB API 的包裝

還有很多可以參考這裡

MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API

Cache API

特性:

  • 主要用來讓 PWA 在離線時能夠使用 response 的 cache
  • Chromium base 的瀏覽器容量為 100 mb,Safari 則是 50mb,而且會在 14 天內過期

使用情境:

  • 在離線的狀況下 cache 文件,這基本上就是 service worker
  • 增進網頁效能

優點:

  • Pormise 為基礎的 API

缺點:

  • 用在 response 以外的資料不太實際
  • Apple 限制多

Cookie

Cookie 嚴格來說並不是 browser storage,因為是依照 client 和 server 之間傳遞的 header 來儲存狀態,而且 server 可以修改資料。

特性

  • 能夠自動過期
  • 數量限制:最多 20 個命名的 cookie,字串的大小最大為 4kb
  • 需要透過 request 還有 response 傳輸,並不是直接存放在 browser 上

能夠利用 JS 操作 cookie 的 API:document.cookie

使用情境:

  • 需要在 server 還有 client 維持少量的狀態:像是 session ID

優點:

  • 登錄基本上都會這麼做
  • 能夠過期,這很重要

缺點:

  • 有限的大小
  • 很爛的 JS API,但覺得會這樣設計就是不太希望透過 JS 去改寫
  • 需要序列化
  • 有可能會被瀏覽器或者 extension 擋掉
  • 法律要求要標示網站使用 cookie
  • 如果數量很大,會導致傳輸過程變慢
    一個 domain 能夠擁有 20 個 4 kb 的 cookie 就代表 80kb,但每個 request 都會傳送出去。如果有 10 個 request 就代表多夾貸了 80kb * 10 * 2(request 和 response) = 1.6mb 的資料

參考網站

未來可用的儲存方式

File System Access API

瀏覽器在一個 Sandbox 執行任何程式,而不是例如像 word 會讀寫電腦上的資料,這可以避免你的資料被奇怪的網站讀取,但這也代表著網頁沒辦法直接修改電腦上的資料,你必須把資料上傳到網頁上,修改,然後再下載下來。

File System Access API 是一個正在草案的 API 可以處理這樣的事情,能夠讀取或者修改你給予權限的資料夾內的檔案,就像任何在電腦上安裝的程式一樣。

使用情境:

  • 你需要操作或儲存本地的檔案
  • 大概還要幾年才支援吧呵呵

優點:

  • web app 會全面入侵 native app
  • 更不需要傳輸資料到 server 了

缺點:

  • 大概只有 Blink engine 會支援吧
  • 到時候 API 舊部一樣了

File and Directory Entries API

這個 API 會以 domain 為單位,建立一個虛擬的本地儲存資料夾,而 JS 就可以在上面操作檔案。

特點:

  • 其實大部份的網站都支援喔
  • 但這不在標準裡面喔

你不太應該使用的儲存方式

window.name

有一個神奇的 session base 屬性 window.name

The name of the window is used primarily for setting targets for hyperlinks and forms. Browsing contexts do not need to have names.

MDN 紀錄是這樣,但不太知道之前是怎麼用的。

但這個東西很神奇的是可以儲存超爆多的資料,有時候會被用來 hack或者是作為 IE7 以前的 local storage 的 polyfill

使用情境:

  • 用在你阿嬤的瀏覽器
  • 不太敏感的資料

優點:

  • 簡單好用的 session base 儲存方式

缺點:

  • 需要序列化
  • 大家都可以存取並修改

WebSQL

特點

  • SQL like 的 DB,用 SQL 語句存取
  • 最大 5mb
  • 效能不太好

2010 年被棄用了,不會再更新

使用情境:

  • 如果你有一個奶奶等級的 APP 正在用,那還是別更新了

優點:

  • 使用 SQL 語法

缺點:

  • 效能差
  • 容量小
  • callback base API
  • 各家實做不太一樣,甚至有些棄用了

App Cache

Cache API 的前身,用一個純文字的檔案來描述要怎麼處理 cache

問題很多,就是個垃圾,可以看這篇

總結

文章裡面寫了一些常用的情境

  • 用一兩個 cookie 儲存 session 狀態
  • 用 DOM storage 來儲存 webcomponent 的狀態
  • Web Storage 儲存簡單的 UI 設定 (dark mode, sidebar size, etc.)
  • IndexedDB for large binary objects and data dumps
  • the Cache API for offline and quick file access
  • JavaScript variables for everything else.

參考網站:
本文幾乎完全整理 & 翻譯自這篇文章