やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

JSのWeb Storage APIを使う(localStorage)

 ローカルにデータを保存する仕組み。

成果物

Web Storage API

Web Storage APIとは、データを保存する仕組みである。  Web Storage APIってなに? という人のために説明しよう。Web Storage APIとは、ブラウザにサイトのデータを保存する仕組みである。JavaScript(ECMAScript)の言語仕様にあるAPIだ。

 Web Storage APIは2種類ある。データを保存する期間に応じて、異なる別のオブジェクトとして用意されている。

Web Storage API ライフタイム
localStorage 永続
sessionStorage 画面遷移するまで(更新も含む)

 Cookieとの共通点は以下。

  • キーバリューである
  • 値の型は文字列のみ
  • ドメイン単位で保存される

 Cookieとなにが違うの? 3つある。Web Storage APIは……。

  1. サーバに送信されない
  2. 暗号化されない
  3. データ上限が多い

 Web Storage APIはサーバに送信されない。Cookieはサーバに自動送信される。CookieはHTTPヘッダに付与され、自動的に送信される。

 Web Storage APIは暗号化されない。Cookieはサーバとの間で送受信するとき、HTTPプロトコルを用いる。これをHTTPSプロトコルに限定することで暗号化できる。

 Web Storage APIはデータ上限が多い。

方法 サイズ
Web Storage API 5MB
Cookie 4KB

 以下のように使い分けるといいだろう。

方法 使い分け
Web Storage API ユーザだけが知っていればいい情報
Cookie サーバがユーザを識別するための情報(HTTPSでセキュアにすべき)
方法 期間 保存するデータ内容 セキュリティ
sessionStorage 画面遷移するまで ユーザだけが知っていればいい情報 なし
localStorage 永久 ユーザだけが知っていればいい情報 なし
Cookie 指定期間 サーバがユーザを識別するための情報 HTTPS限定で暗号化

API

localStorage.length
localStorage.key(INDEX);
localStorage.getItem(KEY);
localStorage.setItem(KEY, VALUE);
localStorage.removeItem(KEY);
localStorage.clear();

localStorage.length

 数を取得する。

 ストレージはドメインごとに保存される。なのでドメインごとに異なる数になりうる。

localStorage.key(INDEX)

 指定した位置にあるキーを取得する。

 lengthと組み合わせることで全キーを取得できる。

function Keys() {
    for (let i=0; i<localStorage.length; i++) {
        yield localStorage.key(i);
    }
}
for (let key in Keys()) {
    console.log(`${key}`);    
}

 全キーとその値を取得する。

for (let i=0; i<localStorage.length; i++) {
    let key = localStorage.key(i);
    let val = localStorage.getItem(key);
    console.log(`${key}=${val}`);
}

localStorage.getItem(KEY)

 指定したキーの値を返す。値の型は文字列である。

let value = localStorage.getItem(KEY);

localStorage.setItem(KEY, VALUE)

 指定したキーの値を設定する。キーと値の型は文字列である。

localStorage.setItem(KEY, VALUE);

localStorage.removeItem(KEY)

 指定したキーの値を削除する。

localStorage.removeItem(KEY);

localStorage.clear()

 このドメインに保存されたすべてのストレージを削除する。

localStorage.clear();

storageイベント

 Storageオブジェクトが変更されるたびに発火する。

window.addEventListener('storage', function(e) {
    e.key;
    e.oldValue;
    e.newValue;
    e.url; // ストレージを変更した文書のURL
    JSON.stringify(e.storageArea); // ストレージオブジェクト自体
});

注意

 Web Storage APICookieと比べて細かい配慮がなされていない。

ドメイン単位で保存される

 Web Storage APICookieと同じく、ドメイン単位で保存される。

問題

 同一ドメイン内で名前重複しうる。同じドメインのうち、異なるページで独立した同じ名前のキーを持ちたいときがある。しかし、同一ドメイン内の同一キーは、ひとつしか持てない。全ページ共通データとなってしまう。

解決

 キー名を一意に保つ。ドメイン内において全ページ間にまたいで全キー名を一意に保つ。

 キー名をdomain.pageID.keyのような構成にする。キー名を一意にするときの階層化には以下のような項目が考えられる。

キー名の部位 内容目的
domain URLのドメイン名|同一ドメインに他プラグインで作成されたキーがあっても重複回避できる
pageID ページの識別子|他のページに同名のキーがあっても重複回避できる
partsID 部品の識別子|同一ページ内における部品ごとに分ける。異なる部品間で同一キーがあっても重複回避できる
key ストレージのキー|値のキー。これだけだと上記パターンで重複してしまいうる

 キーが長くなってしまう。タイポが増えてバグになりうる。防ぐためのクラスを作成するほうが安全だろう。要検討。

有効化パスを指定できない

 Web Storage APICookieと異なり、そのキーごとにロードすべきパスを指定できない。

問題

 動作が遅くなる。同一ドメインの全ページで全ストレージをロードするため。

解決

 使用量を減らす。ストレージは最大5MBだが、使う量を減らす。

 解決にならない。本末転倒である。Web Storage APICookieの4KBと違い、5MBも使えることがメリットだった。それが嬉しくて使っている。なのに、そのメリットがそのまま動作遅延というデメリットになってしまう。

 遅延ロードするか否かについては要調査。もしストレージを遅延ロードしてくれているなら動作速度はいくらかマシになるはず。使うときになってはじめてロードすれば、初期ロード時にすべてロードするときに比べて速い。実際、Web Storage APIが遅延ロードするかどうかはわからなかった。

保存期間が指定できない

 localStorageは保存期間が指定できない。そのため一度保存したら永久に保存されたままになる。

問題

 ファイル残量がなくなる。PCのディスクスペースが圧迫されて何も保存できなくなってしまう。localStorageは一度保存したら削除されないため。

解決

 以下のいずれかの方法をとる。

localStorageを削除する

localStorage.clear();
localStorage.remove(KEY);
問題

 localStorageは使わなくなったデータを削除できない。ストレージの削除は、それを作成したのと同じドメインに遷移せねばならない。だが、そんなことは起こらない。なにせ削除したいのは、もう使わなくなったドメインのデータである。なのに削除するには、その使わなくなったドメインに遷移せねばならない。使っていないのだから遷移するはずがない。したがって、永久に削除できない。

解決

 ブラウザの設定から全データ削除する。たとえばChromiumならメニュー→設定閲覧履歴データの削除で行える。

sessionStorageを使う

 sessionStorageはそのページを閉じたり更新すれば自動削除される。削除し忘れで蓄積することはない。

問題

 セッションをまたいで保存できない。それがしたいからlocalStorageCookieを使っている。なのにそれをやめたら本末転倒。

解決

 なし。sessionStorageはそういうもの。代わりにほかの方法をとるしかない。

Cookieを使うを使う

 Cookieは同一ドメイン内で4KBまでしか使えない。データは厳選されるため、名前重複が起こりにくい。

問題

 同一ドメイン内で4KBまでしか使えない。最も重要なデータのみ保存する。たとえばサーバ側がユーザを特定する情報など。それより優先度がさがるデータは保存できないかもしれない。4KBが上限だから。

解決

 なし。Cookieはそういうもの。代わりにほかの方法をとるしかない。

ブラウザの設定から全データ削除する

 Chromiumならメニュー→設定閲覧履歴データの削除で行える。

問題

 どのドメインのデータを削除するか選べない。削除範囲は期間と項目である。たとえばChromiumなら、現在日時から1時間以内のキャッシュのみを削除するなど。以下でいえばストレージはCookieと他のサイトデータに含まれていると思われる。ただしドメインを選んで削除することはできない。

  • 期間
    • 1時間
    • 1日
    • 1週間
    • 1ヶ月
    • 全期間
  • 項目
    • 閲覧履歴
    • ダウンロード履歴
    • Cookieと他のサイトデータ
    • キャッシュされた画像とファイル
    • パスワードとその他のログインデータ
    • 自動入力フォームのデータ
    • サイトの設定
    • ホストされているアプリデータ

  【Google Chrome】特定のサイト(ドメイン)のCookieだけ削除する方法もある。だが、そもそもユーザは無数にあるドメインからどれを削除するかひとつずつ探しださねばならない。そんな面倒なことをやる人は少ないだろう。

 「私はもう使わない」を自動的に判定するしくみがない。なので楽してデータ削除することができない。

 最悪なワークフロー。しばしば起こりうる。

  1. ブラウザが重くなった
  2. そうだ、履歴データを全削除しよう
  3. localStorageも全削除されてしまう!
解決

 大容量のHDDを使う。

  • 大容量のディスクを使う
  • ディスクの種類はHDDにする(書込上限が多い順:HDD,SSD,eMMC,FlashMemory(USB,SD))

 それでもいずれ寿命はくる。

  1. 買い換える
  2. 楽にOSや環境作成できるよう準備する

所感

 Web Storage APIを使ってみた。とても簡単だった。しかし運用するときに注意すべきことが多い。

 諸悪の根源は、ブラウザのデータ管理方法だと思う。サイトごとのデータを削除する操作になじみがない。もしアプリなら、アプリまるごと削除するという単純な操作で済む。これと同じようにやりたい。アイコンを見て「あ、これ使ってないから消しちゃお」ってしたい。URLなんて覚えていないんだよ。それをキーにサイト検索なんてできるかボケ。

対象環境

$ uname -a
Linux raspberrypi 5.4.72-v7l+ #1356 SMP Thu Oct 22 13:57:51 BST 2020 armv7l GNU/Linux