🫙

Chrome拡張機能のストレージを扱う時に@extend-chrome/storageが便利

2022/11/09に公開

どうも。えーたん(@eetann092)です。

@extend-chrome/storageが便利なので紹介します。

@extend-chrome/storageとは?

@extend-chrome/storageは、Chrome拡張機能のAPIchrome.storageのラッパーです。

メリットは以下の3つです。

  • storageから取得した値の処理をコールバックではなくasync/awaitを使って書くことができる
  • 型情報を追加できる
  • ストレージをBucketとして区切ることができる

実際の例を交えて説明します。

まずはchrome.storageをラッパー無しで使った例です。saveCountchrome.storage.local.setを、loadCountchrome.storage.local.getを使っています。

import { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  const saveCount = () => {
    chrome.storage.local.set({ point: count });
  };

  const loadCount = () => {
    chrome.storage.local.get(["point"], function (result) {
      setCount(result.point);
    });
  };

  return (
    <div className="App">
      <h2>@extend-chrome/storage Example</h2>
      <div>
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
      </div>
      <div>
        <button onClick={saveCount}>Save point</button>
        <button onClick={loadCount}>Load point</button>
      </div>
    </div>
  );
}

export default App;

次に、@extend-chrome/storageを使った例です。

import { useState } from "react";
import { getBucket } from "@extend-chrome/storage";

interface MyBucket {
  point: number;
  person: string;
  color: string;
  name: string;
}

const bucket = getBucket<MyBucket>("my-bucket");

function App() {
  const [count, setCount] = useState(0);

  const saveCount = () => {
    bucket.set({ point: count, person: "eetann", color: "green" });
  };

  const loadCount = async () => {
    const value = await bucket.get();
    setCount(value.point);
  };
  // return以降は同様

分けて説明していきます。

chrome.storageで値を保存・取得してから処理させる場合、コールバック内に書く必要がありました。@extend-chrome/storageを使えば、コールバックではなくasync/awaitを使って書くことができます。

-    chrome.storage.local.get(["point"], function (result) {
-      setCount(result.point);
-    });
+    const value = await bucket.get();
+    setCount(value.point);

型が定義できるため、テキストエディタの補完も効きます。

+import { getBucket } from "@extend-chrome/storage";
+
+interface MyBucket {
+  point: number;
+  person: string;
+  color: string;
+  name: string;
+}
+
+const bucket = getBucket<MyBucket>("my-bucket");

getBucketを使うことでストレージを"Bucket"として区切ることができるため、異なる構造のデータを扱う時に型を分けて定義できます。以下の例では「MyBucketA型のデータを保存するBucketbucket-a」と「MyBucketB型のデータを保存するBucketbucket-b」の2つを定義しています。

const bucketA = getBucket<MyBucketA>("bucket-a");
const bucketB = getBucket<MyBucketB>("bucket-b");

getの形式

getBucketで定義したバケットから値を取得するgetは、引数の書き方によって返ってくる値が異なります。

getの引数が未指定の場合

getの引数が未指定の場合、Bucket全体が返ってきます。

const value1 = await bucket.get();
console.log(value1)
結果の例
{color: 'green', person: 'eetann', point: 5}

getの引数がstring配列の場合

getの引数にstring配列を指定すると、指定したキーと対応する値のみが取り出せます。

const value2 = await bucket.get(["point", "person"]);
console.log(value2)
結果の例
{person: 'eetann', point: 5}

getの引数が文字列の場合

getの引数に文字列を指定すると、指定したキーと対応する値のみが取り出せます。
このようにキーを1つだけ指定しても、取得できる形式は{key: value}です。

const value3 = await bucket.get("point");
console.log(value3)
結果の例
{point: 5}

getの引数がオブジェクトの場合

引数にオブジェクトを指定した場合、そのオブジェクトの中で指定したキーがBucketに存在するかしないかで挙動が変わります。
キーがBucketに存在しない場合、引数で指定した値を返します。
キーがBucketに存在する場合、保存した値が取得できます。

const value4 = await bucket.get({name: "eetann"});
console.log(value4)

上記の例では、nameキーの値を取得しようとしています。すでにキーが存在していれば、Bucketに保存した値を取得できます。存在していない場合、引数で指定したeetannが返ってきます。

キーの一覧も取得できる

getKeysを使えば、キーの一覧を取得できます。

const keys = await bucket.getKeys();
console.log(keys);
結果の例
['color', 'person', 'point']

デフォルトはlocalだけとsyncにもできる

getBucketの第2引数が未指定の場合に対応するAPIはchrome.storage.localですが、syncを指定した場合はchrome.storage.syncになります。

const bucket = getBucket("my-bucket", "sync");

最後に

@extend-chrome/storagegetBucketのAPIは、setgetだけではなくremoveclearにも対応しています。

本記事で扱ったサンプルコードは以下のリポジトリにあります。

https://github.com/eetann/extend-storage-sample

Discussion