Framework
Storage

ストレージAPI

See LicenseNPM InstallFollow PlasmoHQ on TwitterWatch our Live DEMO every FridayJoin our Discord for support and chat about our projects

@plasmohq/storage は、plasmo (opens in a new tab) から提供されるユーティリティライブラリで、ブラウザ拡張機能で使用可能な永続ストレージAPIを抽象化します。拡張機能ストレージAPIが使用できない場合はlocalStorageにフォールバックするため、拡張機能ページ、コンテンツスクリプト、バックグラウンドサービスワーカー、Webページ間で状態を同期できます。

このライブラリは、Plasmoフレームワーク (opens in a new tab)プロジェクトで依存関係として使用した場合、storageパーミッションを自動的に有効にします。

インストール

pnpm install @plasmohq/storage

このパッケージは、ESMとCJSの両方の形式で以下のモジュールをエクスポートします。

モジュール説明
@plasmohq/storage基本的なストレージAPI
@plasmohq/storage/secureセキュアストレージAPI
@plasmohq/storage/hookReactフックストレージAPI

使用例

  • このライブラリを使用してオプションとポップアップ間で状態を同期する方法の例については、with-storage (opens in a new tab) を参照してください。
  • このライブラリをReduxの永続レイヤーとして使用する方法の例については、with-redux (opens in a new tab) を参照してください(MV3にとって重要です)。
  • このライブラリがWebRTCと統合され、拡張機能を介してブラウザ間でメッセージをパイプする実験的なユースケースについては、MICE (opens in a new tab) を参照してください。

ストレージ

基本的なストレージAPIは、使いやすさを重視して設計されています。バックグラウンドサービスワーカー、コンテンツスクリプト、拡張機能ページなど、すべての拡張機能ランタイムで使用できます。

JSON.stringify/parse を使用する必要なく、データを取得/設定できます。保存するデータがシリアライズ可能(プレーンオブジェクトまたはプリミティブ型)であれば、保存できます。

import { Storage } from "@plasmohq/storage"
 
const storage = new Storage()
 
await storage.set("key", "value")
const data = await storage.get("key") // "value"
 
await storage.set("capt", { color: "red" })
const data2 = await storage.get("capt") // { color: "red" }

ストレージ領域のカスタマイズ

ストレージ領域はデフォルトで"sync"に設定されており、これはユーザーがログインしているChromeのすべてのインスタンスでデータが同期されることを意味します。

Plasmoがサポートする他のスコープについては、ChromeストレージAPIドキュメント (opens in a new tab)を参照してください。

const storage = new Storage({
  area: "local"
})

localStorageへのデータの自動コピー

const storage = new Storage({
  copiedKeyList: ["shield-modulation"]
})

上記のコードは、コンテンツスクリプトまたは拡張機能ページで使用する場合、データをWeb localStorageにコピーします。

ウォッチ (状態同期用)

Storage APIを使用する際に変更を監視するには:

background.ts
import { Storage } from "@plasmohq/storage"
 
const storage = new Storage()
 
await storage.set("serial-number", 47)
await storage.set("make", "plasmo-corp")
 
storage.watch({
  "serial-number": (c) => {
    console.log(c.newValue)
  },
  make: (c) => {
    console.log(c.newValue)
  }
})
 
await storage.set("serial-number", 96)
await storage.set("make", "PlasmoHQ")

これは、拡張機能間でメッセージをやり取りするためのレイヤーとして使用できます。with-redux (opens in a new tab)の例で説明しています。

📢

注意: ストレージAPIは、'MAIN'ワールドで実行されるコンテンツスクリプトでは使用できません。Chrome Extensions APIへのアクセスを失うためです。

セキュアストレージ

SecureStorage APIは、静止状態の機密キーの暗号化と復号化によるStorageを拡張します。Web Crypto SubtleCrypto API (opens in a new tab) を使用しており、これはセキュアコンテキスト(HTTPS)でのみ機能します。

import { SecureStorage } from "@plasmohq/storage/secure"
 
const storage = new SecureStorage()
 
await storage.setPassword("roosevelt") // 唯一の違い
 
await storage.set("key", "value")
const data = await storage.get("key") // "value"
 
await storage.set("capt", { color: "red" })
const data2 = await storage.get("capt") // { color: "red" }

ReactフックAPI

フックAPIは、拡張機能のさまざまな部分間の状態同期ワークフローを合理化するために設計されています。多くの使用方法がありますが、まず最初にフックをReactコンポーネントにインポートする必要があります。

import { useStorage } from "@plasmohq/storage/hook"

値を監視してレンダリングする

const [hailingFrequency] = useStorage("hailing")
...
{hailingFrequency}

カスタムストレージインスタンスを使用する

import { Storage } from "@plasmohq/storage"
...
const [hailingFrequency] = useStorage({
  key: "hailing",
  instance: new Storage({
    area: "local"
  })
})

永続化せずに初期値をレンダリングする

"永続化"とは、内部メモリへの書き込みを意味します。

値を永続化しないことで、ストレージに値がない場合、このフックのインスタンスのみが指定された初期値をレンダリングします。他のインスタンスはundefinedを表示するか、独自の初期値を指定できます。詳細については以下を参照してください。

popup.tsxで静的な初期値を設定する場合:

popup.tsx
const [hailingFrequency, setHailingFrequency] = useStorage("hailing", "42")
...
<input value={hailingFrequency} onChange={(e) =>
  setHailingFrequency(e.target.value)
  }/> // "42"

content.tsxでこのキーを購読すると、setHailingFrequencyが定義された値で呼び出されるまでundefinedが表示されます。

content.tsx
const [hailingFrequency] = useStorage("hailing")
 
return <p>{hailingFrequency}</p> // undefined

options.tsxでこのキーを購読しますが、異なる静的な初期値を使用すると、その値が表示されます。

options.tsx
const [hailingFrequency] = useStorage("hailing", "147")
 
return <p>{hailingFrequency}</p> // "147"

上記のセットアップで、上記のいずれかのインスタンスでsetHailingFrequency("8472")を呼び出すと、すべてのインスタンスに "8472" が表示され、初期値ではなくストレージの値を追跡するようになります。

初期値をレンダリングして永続化する

静的な値ではなく関数を使用することで、初期値がストレージメモリに永続化されます。初期化関数は、ストレージ内の既存の値である1つのパラメータを持ちます。値がない場合はundefinedです。

ストレージに何もない場合に状態を "42" に初期化するpopup.tsxがあるとします。

popup.tsx
const [hailingFrequency, setHailingFrequency] = useStorage("hailing", (v) => v === undefined ? "42": v)
...
{hailingFrequency} // "42"

その後、content.tsxまたはoptions.tsxで新しいフックインスタンスを作成すると、setHailingFrequencyを呼び出さなくても、永続化された初期値が表示されます。

content.tsx
const [hailingFrequency] = useStorage("hailing")
 
return <p>{hailingFrequency}</p> // "42"

高度な使用方法

フォーム入力やリアルタイム入力を行う場合は、次のものが必要になる場合があります。

const [hailingFrequency, setHailingFrequency, {
  setRenderValue,
  setStoreValue,
  remove
}] = useStorage("hailing")
 
return <>
  <input value={hailingFrequency} onChange={(e) => setRenderValue(e.target.value)}/>
  <button onClick={() => setStoreValue()}>
    保存
  </button>
  <button onClick={() => remove()}>
    削除
  </button>
</>
 

Firefoxでの使用

開発中にFirefoxでストレージAPIを使用するには、マニフェストにアドオンIDを追加する必要があります。追加しないと、次のエラーが発生します。

エラー: ストレージAPIは一時的なアドオンIDでは機能しません。マニフェストに明示的なアドオンIDを追加してください。詳細については、https://mzl.la/3lPk1aE (opens in a new tab) を参照してください。

マニフェストにアドオンIDを追加するには、package.jsonに以下を追加します。

"manifest": {
  "browser_specific_settings": {
    "gecko": {
      "id": "your-id@example.com"
    }
  }
}

アドオンIDの形式は、マニフェストのバージョンによって異なります。

  • Manifest V2: your-id@example.com
  • Manifest V3: {ed7ba470-8e54-465e-825c-99712043e01c} (任意のUUID)

拡張機能を公開すると、package.jsonファイルで定義されているアドオンIDは、拡張機能の開発者ページの_"技術情報 > UUID"_に表示されるはずです。

注: 開発中に使用されるアドオンID(つまり、マニフェストで定義されているID)は、公開時にMozillaが割り当てるIDと同じである可能性があります。そうでない場合、およびIDが生成された場合は、新しいIDを使用してpackage.jsonファイルを更新する必要があります。

アドオンIDは一意であり、複数の拡張機能(マニフェストのバージョンに関わらず)で同じIDを使用することはできません。