? 首個瀏覽器內建模組 kv-storage 非同步版的 localStorage

JS菌 發表於 2019-03-20
localStorage

20190320233353.png

瀏覽器內建模組 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 物件,也就是說這些都是非同步的 ?

20190320222926.png

官網規範:wicg.github.io/kv-storage/…

不說那麼多,先來看看這個內建模組到底怎麼用:

環境配置

首先我們需要一個 74 版本以上的 Chrome 瀏覽器,並且需要開啟 chrome://flags/#enable-experimental-web-platform-features

20190320223227.png

瀏覽器需要支援 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,我們來看看效果:

輸入資料並點選儲存:

20190320225831.png

我們去 indexdDB 中檢視資料是否儲存成功:

20190320225927.png

預設在 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/) 也已經在業內很頻繁在用了。作為第一個內建模組,雖現在不建議在生產模式中使用,但足以遇見在不久的將來這中內建模組的方式可能成為一種趨勢。

參考: