参考・関連リンク
- KV Storage: the Web's First Built-in Module | Web
- WICG/kv-storage - github
- GoogleChromeLabs/kv-storage-polyfill - github
- tc39/proposal-javascript-standard-library - github
- WICG/import-maps - github
注意
- この記事内での引用は以下の参考サイトのgoogle翻訳です
記事の内容に間違いなどありましたらご指摘お願いします
KV Storageとは
ブラウザベンダやWebパフォーマンスの専門家は、この10年間の大部分でlocalStorageは動作が遅く、Web開発者はそれを使うのをやめるべきだと言ってきました。
公平に言うと、これを言っている人々は間違っていません。 localStorageは、メインスレッドをブロックする同期APIです。アクセスするたびに、ページがインタラクティブに表示されなくなる可能性があります。
問題は、localStorage APIが非常に単純で、localStorageの唯一の非同期的な代替方法がIndexedDBであることです。これは(使いやすさや使いやすさのために知られていません)。
そのため、開発者は使いにくいものとパフォーマンスに悪いもののどちらかを選択できます。そして、実際には非同期ストレージAPIを実際に使用しながらlocalStorage APIのシンプルさを提供するライブラリもありますが、その中にはファイルサイズのコストがかかり、パフォーマンスの予算を浪費する可能性があります。
しかし、ファイルサイズのコストを支払う必要なしに、localStorage APIの単純さで非同期ストレージAPIのパフォーマンスを得ることが可能だったらどうでしょうか。
まあ、すぐにあるかもしれません。 Chromeは組み込みモジュールと呼ばれる新機能を試しています。最初に出荷する予定の機能は、KV Storageという非同期のキー/値ストレージモジュールです。
localStorageと違い非同期で、かつ簡単に扱える、KV Storage (Key-Value型データベース)の機能のようです。
動くサンプル
chromeのバージョン73だと動かすことができません。※2019/03/31現在
Note: The KV Storage module is currently available in Chrome 74 if you have the experimental web platform features flag turned on: (chrome://flags/#enable-experimental-web-platform-features).
参考ページにある通りに、実験用Webプラットフォーム機能フラグをonにすると動かすことができたので、この記事ではその状態で試していきます。
chrome://flags/#enable-experimental-web-platform-features
こちらを Enabled
にしてchromeを再起動する
ほぼ参考ページのサンプル通りですが、このように簡単に動かすことができました
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="module">
import { storage } from "std:kv-storage";
(async () => {
const oldPreferences = await storage.get("preferences");
document.querySelector("form").addEventListener("submit", async e => {
e.preventDefault();
const newPreferences = Object.assign({}, oldPreferences, {
date: new Date().toLocaleString()
});
await storage.set("preferences", newPreferences);
console.log(await storage.get("preferences"));
});
})();
</script>
</head>
<body>
<form><input type="submit"></form>
</body>
</html>
ブラウザ対応
polyfillを使う
$ npm i kv-storage-polyfill
参考ページの通りだとこういう書き方になるようです
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="importmap">
{
"imports": {
"/node_modules/kv-storage-polyfill/dist/kv-storage-polyfill.mjs": [
"std:kv-storage",
"/node_modules/kv-storage-polyfill/dist/kv-storage-polyfill.mjs"
]
}
}
</script>
<script type="module">
import { storage } from '/node_modules/kv-storage-polyfill/dist/kv-storage-polyfill.mjs';
(async () => {
const oldPreferences = await storage.get('preferences');
document.querySelector('form').addEventListener('submit', async e => {
e.preventDefault();
const newPreferences = Object.assign({}, oldPreferences, {
date: new Date().toLocaleString()
});
await storage.set('preferences', newPreferences);
console.log(await storage.get('preferences'));
});
})();
</script>
</head>
<body>
<form><input type="submit"></form>
</body>
</html>
参考:https://github.com/WICG/import-maps#for-built-in-modules-in-browsers-without-import-maps
参考に書いてあることのまんまですが、以下のように動作してくれるとのことです
- importmapをサポートしていないブラウザはpolyfillを受け取ります
- importmapをサポートしているがKV Storageをサポートしていないブラウザは、polifillのURLからそれ自体へのマッピングになるので、polifillを受け取ります
- importmapとKV Storageの両方をサポートするブラウザは、polyfill URLからstd:kv-storageへのマッピングになるため、組み込みモジュールを受け取ります
polyfillを使うことで、Safariでも動作することが確認できました
API
※以下を参考にいくつか試してみました、詳細知りたい方は以下を参考にしてください
基本的な使い方
<script type="module">
import { storage } from "std:kv-storage";
(async () => {
console.log(await storage.get("category")) // undefind
await storage.set("category", "hoge"); // 値をセット
console.log(await storage.get("category")) // hoge
await storage.delete("category"); // 値を削除
console.log(await storage.get("category")) // undefind
await storage.set("foo", 1);
await storage.set("bar", 2);
for await (const [key, value] of storage.entries()) {
console.log(key, value); // 「foo 1」「bar 2」がそれぞれ出力
}
await storage.clear() // 全て削除
console.log(await storage.get("foo")) // undefind
console.log(await storage.get("bar")) // undefind
})();
</script>
new StorageArea()
new StorageArea
とすることで、データをそこに保存することができます。
キー名が衝突する可能性が低くなります
<script type="module">
import { storage, StorageArea } from "std:kv-storage";
(async () => {
await storage.set("mycat", "Tom");
console.assert(await storage.get("mycat") === "Tom");
const otherStorage = new StorageArea("unique string");
console.assert(await otherStorage.get("mycat") === undefined);
await otherStorage.set("mycat", "Jerry");
console.assert(await otherStorage.get("mycat") === "Jerry");
})();
</script>
最後まで読んでいただいてありがとうございましたm(_ _)m