過去十年來,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
。
storage
是 StorageArea
類別的執行個體,名稱為 '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 指令碼。而是會看到內建的模組版本 (其實:實際上,您可以檢查模組的原始碼,甚至在其中加入中斷點!):
請提供寶貴意見
本簡介應讓您瞭解內建模組可能會提供哪些功能。希望你躍躍欲試!我們非常希望開發人員能試用 KV 儲存空間模組 (以及本文討論的所有新功能),並提供意見回饋。
請參閱下列 GitHub 連結,您可以針對本文提及的各項功能提供意見回饋:
如果您的網站目前使用 localStorage
,建議您改用 KV Storage API,看看是否符合所有需求。如果您申請 KV 儲存空間來源試用,可以立即部署這些功能。因此,貴機構的使用者應能享有更優異的儲存空間效能,Chrome 74 以上版本使用者也無須支付額外的下載費用。