0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Chrome拡張でSessionStorageを使う注意点その対策

Last updated at Posted at 2025-07-15

Chrome拡張でコンポーネント間の値の共有一時的な状態保持のためにSessionStorageを使ったところ、意図せずバグを仕込んでしまった体験と、その解決策を紹介します。


背景:なぜSessionStorageを使ったのか?

Chrome拡張では、window.sessionStorage などの ブラウザが提供するStorage API に加えて、chrome.storage.local や chrome.storage.session といった 拡張機能専用のストレージ も利用できます。

それぞれ使える場所やスコープが異なるため、用途に応じた使い分けが重要です

今回は、下記の理由で使いたくない場面がありました。

ストレージ 問題点
chrome.storage.local 全タブで共有されてしまい、ページごとに独立して保持したい状態には不向き
chrome.storage.session Manifest V3かつServiceWorker限定。backgroundからしか使えず、content scriptからの直接操作不可

スクリーンショット 2025-07-16 8.21.32.png

そのため、ページ単位で状態が保持され、タブごとに独立して使えるSessionStorage をcontent scriptで採用しました。


問題

うまく行ったと思ったのですが、結合テストをするとき何回かに1回、意図しないデータ参照が発生していることに気が付きました。

APIのリクエストパラメータがひとつ遷移する前ページの内容を引き継いでいることに

問題の詳細

対象のWebサイトは以下のような構成:

商品Aのページ
https://example.com/item?id=ti-kawa

商品Bのページ
https://example.com/item?id=hachiware

このようにクエリパラメータでコンテンツ(商品ページ)が切り替わる設計です。

ところが SessionStorage は「オリジン単位+タブ単位」でデータを保持するため、別の商品ページでも同じSessionStorageが共有されてしまうのです。

Amazon.co.jpの例

スクリーンショット 2025-07-16 6.40.06.png

起きた不具合

前のページで保存された状態が、新しいページでそのまま参照されてしまい、整合性のないAPIリクエストが飛んでしまうという事態に。


なぜこうなるのか?SessionStorageの特性

sessionStorage は「タブごとに1つのストレージ空間」を持ちます

URLが異なっても、オリジンが同じなら共有される(クエリパラメータやパスは区別されない)仕様になっております。

つまり「別商品」であっても「同一sessionStorage」として扱われてしまうため、エラーが起こっていました。


解決策:URLをキーに含めることで分離管理

対策1:URL別にキーを分ける

const key = `page-state:${location.pathname}?${location.search}`;
sessionStorage.setItem(key, JSON.stringify(state));
  • クエリやパス込みでキーを構成すれば、商品ごとに独立した保存が可能に
  • 読み取りも同様に現在のURLに応じて参照
const currentKey = `page-state:${location.pathname}?${location.search}`;
const saved = sessionStorage.getItem(currentKey);

対策2:初期データは毎回APIから取得する

SessionStorageに依存しすぎず、ページ遷移時は毎回データ取得する設計に変更。
SessionStorageは「中間入力の保持」や「直近のUI状態保存」などに用途を限定。


その他の補足

sessionStorageの代替:chrome.storageは?

ユーザーのログイン状態など、拡張全体で一貫した状態管理をしたい場合には、chrome.storage.localを使うのが適しています。

ただしこれは全タブで共有されるため、今回のように 「ページ単位で切り離したい一時的な状態」 を扱うには工夫が必要です。

また、拡張機能専用の chrome.storage.session もありますが、ServiceWorker(background)限定でしか使えず、popup や content script からはアクセスできません。

スクリーンショット 2025-07-16 8.18.13.png

そのため、ユーザーの目に見える画面単位でのセッション状態を管理したい場合、window.sessionStorage(DOM API)を使わざるを得ないケースも残ります。


まとめ

  • sessionStorageは便利だが、URL単位では分離されないことに注意
  • 特に「クエリパラメータでページを識別している」サイトでは注意が必要
  • 対策としては、URLをキーに含める or 毎回取得設計にする

SessionStorageは手軽に使える反面、思わぬ「つまずきポイント」が潜んでいます。

特にChrome拡張の開発においては、chrome.storage.session(Extensionのセッションストレージ)はbackgroundスクリプト専用であり、popupやcontent scriptからは参照できないという制約があります。

そのため、画面ごとの一時的な状態管理には実質的にwindow.sessionStorageを使うしかない場面も多く、選択肢が限られているのが実情です。

とはいえ、設計やキーの工夫次第で、こうした制約下でも安全かつ意図した挙動を実現できます。
同じような課題に悩む方の一助となれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?