瀏覽器內建模組 kv-storage 非同步版的 localStorage
LocalStorage 大家都不陌生基本上每天都在跟他打交道。但這是個會阻塞主執行緒的同步 API,很多情況下存取大量資料可能會造成效能問題。?
為了解決這個問題,我們可能會使用 IndexedDB,但後者難以操作,雖然目前有第三方模組可以很輕鬆操作 IndexedDB,但仍然不是最好的解決方案。
有沒有一種既能夠像 LocalStorage 一樣簡單的 API,又能夠擁有 IndexedDB 這樣的非同步存取資料的能力的前端儲存解決方案呢❓
這個時候 Chrome 開發團隊目前正在測試一款名為 std:kv-storage
的 瀏覽器內建模組 ?
啥是內建模組?
內建模組 Built-in modules 跟 JS 模組一樣,只不過他並不用從遠端下載下來使用,而是與瀏覽器繫結在一起的。
當然,這種內建模組與傳統的 web API 最大的不同之處就是需要使用 esm 語法進行匯入 ⬇️,這種模組並不會暴露在全域性作用域中,你沒辦法直接通過 window.xxx
來引用,而是需要先 import
在 chrome 中內建模組的識別符號是 std:
kv-storage
kv-storage 模組在 API 上與 LocalStorage 類似。常用的方法有:
- get() 讀取資料
- set() 寫入資料
- delete() 刪除資料
- clear() 清空資料
所有的上述方法都會返回一個 Promise 物件,也就是說這些都是非同步的 ?
不說那麼多,先來看看這個內建模組到底怎麼用:
環境配置
首先我們需要一個 74 版本以上的 Chrome 瀏覽器,並且需要開啟 chrome://flags/#enable-experimental-web-platform-features
瀏覽器需要支援 modules 在 Chrome 中,要求版本在 61 以上
編寫演示程式碼
首先這裡用一個 index.html 檔案配合 vscode 的 Live Server 做演示
我們要做的一個簡單的功能是建立一個表單,使用者填寫表單過程中,點選儲存按鈕,填寫在表單內的資料都會儲存在 kv-storage 中,即便使用者不小心重新整理了瀏覽器,點選恢復按鈕即可恢復資料。
首先我們需要一個表單:
<form action="">
<input type="text" name="username" placeholder="username">
<input type="text" name="message" placeholder="message">
<button type="submit">儲存</button>
<button type="reset">恢復</button>
</form>
複製程式碼
然後定義一個 type 為 module 的 script 標籤
<script type="module"></script>
script 標籤內就是我們的主要邏輯:
<script type="module">
import { storage } from 'std:kv-storage' // 首先匯入內建模組 kv-storage
{
(async () => {
// 定義兩個事件處理函式
document.querySelector('form').addEventListener('submit', handleClickSubmit)
document.querySelector('form').addEventListener('reset', handleClickRestore)
// 當點選儲存
async function handleClickSubmit(e) {
e.preventDefault()
let inputs = document.querySelector('form').querySelectorAll('input')
let kvData = Array.from(inputs).map(item => ({ name: item.getAttribute('name'), value: item.value }))
await storage.set('formData', kvData) // 獲取表單資料並儲存在在 key 為 formData 的 store 中
}
// 恢復資料事件處理函式
async function handleClickRestore(e) {
let formData = await storage.get('formData') // 讀取 formData 資料
document.querySelector('form').querySelectorAll('input')
formData.forEach(data => {
let { name, value } = data
document.querySelector(`input[name=${name}]`).value = value // 將資料注入 input 元素內
})
}
})()
}
</script>
複製程式碼
以上,非常簡單的一個 DEMO,我們來看看效果:
輸入資料並點選儲存:
我們去 indexdDB 中檢視資料是否儲存成功:
預設在 kv-storage:default
資料庫的 store 集合中出現一條 formData 資料,值就是表單資料陣列
然後我們重新整理瀏覽器並點選恢復,kv-storage 從 indexedDB 中又讀取了資料並注入到表單中
即便是關閉瀏覽器重新開啟依然能夠恢復資料
主要的使用方法大概就是這樣,目前位置該內建模組仍然在測試中。
相容
官方給了一套相容性解決方案,針對檢測是否存在該內建模組的 import map
方法;還有針對是否支援 modules 的 nomodules
方案。
檢測是否存在內建模組
新增標籤設定 type 為 importmap 建立 importmap,當使用 import 方法引入模組的時候,按照路徑首先檢查是否能夠通過 import {storage} from 'std:kv-storage'
引入,如果不可以,則嘗試使用 polyfill import {storage} from '/path/to/kv-storage-polyfill.mjs
<!-- The import map is inlined into your page -->
<script type="importmap">
{
"imports": {
"/path/to/kv-storage-polyfill.mjs": [
"std:kv-storage",
"/path/to/kv-storage-polyfill.mjs"
]
}
}
</script>
<!-- Then any module scripts with import statements use the above map -->
<script type="module">
import {storage} from '/path/to/kv-storage-polyfill.mjs';
// Use `storage` ...
</script>
複製程式碼
相關文件見:github.com/WICG/import…
檢測是否支援 modules
<!-- 支援 ES Modules 的瀏覽器載入 main.mjs -->
<script type="module" src="main.mjs"></script>
<!-- 舊瀏覽器不支援 ES Modules 會載入該檔案,同時支援 ES Modules 會忽略這個檔案 -->
<script nomodule src="main.es5.js"></script>
複製程式碼
這裡附上 polyfill:github.com/GoogleChrom…
Chrome 釋出的 kv-storage 並不是說有多麼的強大,畢竟現在 LocalForage(localforage.docschina.org/) 也已經在業內很頻繁在用了。作為第一個內建模組,雖現在不建議在生產模式中使用,但足以遇見在不久的將來這中內建模組的方式可能成為一種趨勢。
參考: