KV 儲存體 - 網頁';第一個內建模組

過去十年來,localStorage 速度緩慢,瀏覽器供應商和網頁效能專家表示,他們應該停止使用這項工具。

出於公正,民眾認為這並非是錯的。localStorage 是一種同步 API,會封鎖主執行緒,而存取主要執行緒時,都有可能導致網頁無法互動。

localStorage API 本身就是這麼簡單,但 localStorage 唯一的非同步替代方式是 IndexedDB,但這項實作方式並不簡單或容易上手的 API。

因此,開發人員有權選擇難用或效能不佳的東西。雖然「有些」程式庫可讓您輕鬆使用 localStorage API,同時實際使用非同步儲存空間 API,應用程式中的其中一個程式庫也會產生檔案大小,因此可能會耗用您的效能預算

但是,如果只需簡化 localStorage API,就能取得非同步儲存空間 API 的效能,而且無須支付檔案大小的費用,該怎麼辦?

啊,你很快也許會了。Chrome 正在實驗一項名為「內建模組」的新功能,而我們計劃推出的第一個功能,是名為「KV Storage」的非同步鍵/值儲存空間模組。

在深入說明 KV 儲存空間模組之前,我想先說明何謂內建模組

什麼是內建模組?

內建模組就像一般 JavaScript 模組,不過由於這類模組隨附於瀏覽器,因此不用下載。

和傳統 Web API 一樣,內建模組和傳統 Web API 一樣須經過標準化程序。每個內建模組都有各自的規格,需要經過設計審查,並需要網站開發人員和其他瀏覽器廠商提供的正面徵兆,才能推送出去。(在 Chrome 中,內建模組將遵循我們用於實作及提供所有新 API 的啟動程序)。

與傳統 Web API 不同的是,內建模組不會在全域範圍內公開,只能透過匯入取得。

不公開內建模組有很大的優勢:啟動新的 JavaScript 執行階段結構定義 (例如新分頁、工作站或 Service Worker) 並不會增加任何負擔,而且除非實際匯入,否則不會耗用任何記憶體或 CPU。此外,這些程式碼也不會因為程式碼中定義的其他變數而發生命名衝突。

如要匯入內建模組,請使用前置字串 std:,後面加上內建模組的 ID。例如,在支援的瀏覽器中,您可以使用下列程式碼匯入 KV 儲存空間模組 (請參閱下方說明,瞭解如何在不支援的瀏覽器中使用 KV Storage polyfill):

import storage, {StorageArea} from 'std:kv-storage';

KV 儲存空間模組

KV Storage 模組與 localStorage API 相當簡單,但其 API 形狀其實更接近 JavaScript Map。其有 get()set()delete(),而非 getItem()setItem()removeItem()。而且還有 localStorage 無法使用的其他類似方法,例如 keys()values()entries(),就跟 Map 一樣,其索引鍵不一定要是字串。這類序列可以是任何結構化序列化類型

Map 不同,所有 KV Storage 方法都會傳回承諾非同步疊代器 (因為此模組的主要重點不是同步,與 localStorage 相比)。如要詳細查看完整的 API,請參閱規格

您可能已經注意到,在上方的程式碼範例中,KV 儲存空間模組有一個預設匯出 storage 和一個具名匯出 StorageArea

storageStorageArea 類別的執行個體,名稱為 'default',這是開發人員最常在應用程式的程式碼中使用。如果需要使用額外隔離的情況 (例如儲存資料的第三方程式庫,並希望避免與透過預設 storage 執行個體儲存的資料發生衝突),我們提供 StorageArea 類別。StorageArea 資料會儲存在名為 kv-storage:${name} 的 IndexedDB 資料庫中,其中名稱為 StorageArea 執行個體的名稱。

以下範例說明如何在程式碼中使用 KV 儲存空間模組:

import storage from 'std:kv-storage';

const main = async () => {
  const oldPreferences = await storage.get('preferences');

  document.querySelector('form').addEventListener('submit', async () => {
    const newPreferences = Object.assign({}, oldPreferences, {
      // Updated preferences go here...
    });

    await storage.set('preferences', newPreferences);
  });
};

main();

如果瀏覽器不支援內建模組,該怎麼辦?

如果您很熟悉在瀏覽器中使用原生 JavaScript 模組,很可能會知道 (至少到現在) 匯入網址以外的任何內容會產生錯誤。而且 std:kv-storage 不是有效的網址。

這也引發了這個問題:我們是否需要等到所有瀏覽器都支援內建模組後,才能在程式碼中使用該模組?但幸好答案不會!

即使某個瀏覽器支援這些內建模組,您仍可直接使用內建模組;這是因為我們正在實驗這項名為「匯入地圖」的另一項功能。

匯入地圖

「匯入地圖」基本上是一種機制,可讓開發人員為一或多個替代 ID 設定別名的匯入 ID。

這項功能十分強大,可讓您變更 (在執行階段) 瀏覽器如何解析整個應用程式中的特定匯入 ID。

如果是內建模組,這可讓您在應用程式程式碼中參照模組的 Polyfill,但支援內建模組的瀏覽器也可改為載入該版本!

以下說明如何宣告匯入對應,以便搭配 KV Storage 模組使用:

<!-- 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>

上述程式碼的重點是,將網址 /path/to/kv-storage-polyfill.mjs 對應至「兩項」不同的資源:std:kv-storage,然後是原始網址 /path/to/kv-storage-polyfill.mjs

因此,當瀏覽器遇到參照該網址 (/path/to/kv-storage-polyfill.mjs) 的匯入陳述式時,會先嘗試載入 std:kv-storage,如果無法載入,便會重新載入 /path/to/kv-storage-polyfill.mjs

再次強調,由於要傳遞至匯入陳述式的網址是 polyfill 的網址,因此瀏覽器不需要支援匯入地圖「或」內建模組,這項技巧就能運作。polyfill 實際上不是備用選項。內建模組是漸進式的增強功能!

如果瀏覽器完全不支援模組,該怎麼辦?

如要使用匯入對應功能以條件方式載入內建模組,您必須確實使用 import 陳述式,這表示您必須使用「模組指令碼」,也就是 <script type="module">

目前超過 80% 的瀏覽器支援模組,如果瀏覽器不支援模組,您可以使用 module/nomodule 技術提供舊版套件。請注意,產生 nomodule 版本時,您必須加入所有 polyfill,因為您知道不支援模組的瀏覽器絕對不支援內建模組。

KV 儲存空間示範

為了說明即使仍支援舊版瀏覽器,也能使用內建模組,我們整理了示範,其中整合了上述所有技術,目前可在所有瀏覽器中運作:

  • 支援模組、匯入地圖和內建模組的瀏覽器不會載入任何不必要的程式碼。
  • 如果瀏覽器支援模組和匯入地圖,但不支援內建模組,請透過瀏覽器的模組載入器載入 KV Storage polyfill
  • 如果瀏覽器支援模組但不支援匯入地圖,也會透過瀏覽器的模組載入器載入 KV 儲存空間 polyfill。
  • 如果瀏覽器完全不支援模組,舊版套件中就會提供 KV 儲存空間 Polyfill (透過 <script nomodule> 載入)。

示範內容由 Glitch 代管,方便您查看原始碼。 如需實作方式的詳細說明,請參閱 README。如果你有興趣瞭解這款手機是怎麼建構的,歡迎看看。

如要實際查看原生內建模組的實際運作情形,您必須在 Chrome 74 以上版本中載入示範,並開啟實驗性網路平台功能旗標 (chrome://flags/#enable-experimental-web-platform-features)。

您可以確認內建模組是否順利載入,因為開發人員工具中的來源面板不會顯示 polyfill 指令碼。而是會看到內建的模組版本 (其實:實際上,您可以檢查模組的原始碼,甚至在其中加入中斷點!):

Chrome 開發人員工具中的 KV 儲存空間模組來源

請提供寶貴意見

本簡介應讓您瞭解內建模組可能會提供哪些功能。希望你躍躍欲試!我們非常希望開發人員能試用 KV 儲存空間模組 (以及本文討論的所有新功能),並提供意見回饋。

請參閱下列 GitHub 連結,您可以針對本文提及的各項功能提供意見回饋:

如果您的網站目前使用 localStorage,建議您改用 KV Storage API,看看是否符合所有需求。如果您申請 KV 儲存空間來源試用,可以立即部署這些功能。因此,貴機構的使用者應能享有更優異的儲存空間效能,Chrome 74 以上版本使用者也無須支付額外的下載費用。