JSのsessionStorageを使う
ブラウザを閉じる間まで保存する。
成果物
sessionStorage
sessionStorageは、そのページを開いてから、そのタブまたはブラウザが閉じられるまでデータを保存する。その間であればページ更新をされても保存されたままである。
API
sessionStorage.length sessionStorage.key(INDEX); sessionStorage.getItem(KEY); sessionStorage.setItem(KEY, VALUE); sessionStorage.removeItem(KEY); sessionStorage.clear();
詳しくはJSのWeb Storage APIを使うを参照。
使い所がない
sessionStorageの使い所が見つからない。
ブラウザを閉じる間まで保存したいデータって?
ブラウザを閉じる間まで保存したいデータってある? なくね?
Cookieでさえローカルに保存される。セッションの間だけ使うデータだとしてもローカルに保存されている。対してsessionStorageはどこにも保存されない。ローカルにもサーバにも。ブラウザやタブを閉じたら完全に削除される。復元できない。
Web Storage APIには暗号化する仕組みがない。個人情報なんて保存したらセキュリティ・ホールになってしまう。そもそもsessionStorageは閉じたら削除される。それでも、閉じるまでの間はJSコードから情報収拾できるし、中身も平文で閲覧できてしまう。
閉じる間まで保存したいデータなんてないのでは?
DOMでいいのでは?
ブラウザを閉じる間まで保存できればいいのであれば、HTML(DOM)でいいのでは? sessionStorageを使う必要ある?
以下のときはDOMで実現できない。なのでsessionStorageを使う必要がある。だが、やはり閉じると削除されるのがネック。
グローバル変数はバット・プラクティスでは?
sessionStorageはグローバル変数である。グローバルオブジェクトwindow
がsessionStorageを持っているため、どこからでもアクセスできる。つまりグローバル変数だ。
グローバル変数はバット・プラクティスである。スコープは必要最小限にするのがベスト・プラクティスである。保存した値は参照できる範囲を適切に制限すべきである。だが、それができない。sessionStorageはグローバル変数だから。保存した値はどこからでも参照できてしまう。
バグの温床になる。カプセル化できないため。
バグの温床になる。適切な値をセットする責任をもったコードの範囲を制限できないため。
デバッグが大変。もし不正値をセットされていたら、どのコードで行われたか全ファイルを見なくてはならない。
テストが大変。品質を保障するには、たとえ関係ないコードを変更したときでも、全テストをやり直さねばならない。いちいちコードをみて「ここは関係ない」と判断すること自体に時間と労力がかかるし、ミスが生じてバグになりうるから。
名前が重複しやすい。スコープが広いため。
sessionStorageはDOMよりスコープが広い。ページ内グローバルではなく、ドメイン内グローバルである。そのくせ、データを特定するのはキーという文字列のみ。名前重複しまくるだろう。せめて名前空間みたいな概念があって階層化できたりしたらよかったのに。そんなことできない。なんてバットなプラクティスなんだ。
使い所をムリヤリ考える
インメモリDBと考えればいいと思う。
条件
以下の条件を満たすなら、sessionStorageの使い所である。
- タブやブラウザを閉じたら削除されていい
- 同一タブ内にて同一ドメインサイトにおける複数の異なるページ間で同じ値を使いたいとき
- 取得されても問題ないデータである(個人情報でない)
- タブ間で共有しなくていい
- タブ間で同期しなくていい
タブやブラウザを閉じたら削除されていい
致命的。この条件でもう離脱する。
Cookieのセッション情報でさえサーバ側に保存される。なのにsessionStorageはタブを閉じたらもうどこにも保存されない。いやいや、せめてローカルに保存したい。なのでlocalStorageのほうを使いたくなる。
同一タブ内にて同一ドメインサイトにおける複数の異なるページ間で同じ値を使いたいとき
ここがポイント。sessionStorageの使い所はここだ。
HTML(DOM)はページ内グローバル変数である。対してsessionStorageはドメイン内グローバル変数である。つまりHTML(DOM)よりスコープが広い。なので、もし複数の異なるページ間でデータを共有したいならsessionStorageを使うのがいい。
ただし、タブを閉じたら削除されてしまう。それ、HTML(DOM)と同じじゃないか。せめてローカルに保存したい。なのでやはりlocalStorageを使うことになる。
取得されても問題ないデータである(個人情報でない)
保存されたデータは暗号化されない。暗号化する仕組みもない。Web Storage APIを使うなら、自前で暗号化せねばならない。
Cookieなら設定次第でHTTPSによりセキュアに保存することができるのに。
タブ間で共有・同期しなくていい
sessionStorageはデータを異なるタブ間で共有・同期できない。
これは問題にならないだろう。おそらくそんな要件はあまりない。仮にあるのだとしたら、localStorageのほうを使ってstorage
イベントを使うことになる。sessionStorageではイベントが発火しない。
案
2段階
sessionStorageで保存し、閉じるときlocalStorageで保存する2段構え。これならsessionStorageを使える。でも、使う意味・価値がない。
- sessionStorageでドメイン内データをグローバル変数として一元管理する
- 閉じるとき、localStorageでsessionStorageデータを保存する
だったら、最初からステップ2だけやればいいのでは? はい、そのとおりです。
localStorageさえあればよくね? はい、そのとおりです。
sessionStorage要らなくね? はい、そのとおりです。
所感
sessionStorageは使わず、localStorageを使おう。
対象環境
- Raspbierry pi 4 Model B
- Raspberry Pi OS buster 10.0 2020-08-20 ※
- bash 5.0.3(1)-release
$ uname -a Linux raspberrypi 5.4.72-v7l+ #1356 SMP Thu Oct 22 13:57:51 BST 2020 armv7l GNU/Linux