HTTP / WebSpec

ブラウザの localStorage(ローカルストレージ)とは

自作のツールでデータの保存先に使ってみて、はじめて存在を知りました。普段は DB やバッチ処理が中心なので、DB にたとえながら整理しておきます。

localStorage とは

ブラウザの中にある、サイトごとの小さな保存領域です。キーと値(どちらも文字列)だけを保存でき、ブラウザを閉じても消えません。

項目localStorageDB にたとえると
データの形キーと値(どちらも文字列)。オブジェクトは JSON の文字列にして入れる主キーと値の 2 列だけのテーブル
大きさの上限サイトごとに約 5〜10MB小さな作業用のテーブル
保存期間消すまでずっと残る永続的なテーブル
操作setItem / getItem / removeItem くらいINSERT、SELECT、DELETE だけ。SQL もトランザクションもない
どこにあるか利用者の PC のブラウザの中サーバーではなくクライアント側

普通のサイトでも使われている

このブログ(WordPress + AdSense)でも見てみたら、自分では何も書いていないのに、Google AdSense が google_ama_config(自動広告の設定、約 3 万文字)などを保存していました。広告やアクセス解析などの外部のスクリプトが、裏で使っていることも多いです。

オリジンごとに分かれている

localStorage はオリジン(スキーム+ホスト+ポート)ごとに完全に分かれています。

  • https://example.com と https://www.google.com は別々の localStorage
  • ほかのサイトの localStorage は読めない(同一オリジンポリシー)

DB で言えば、スキーマごとに権限が完全に分かれていて、別のスキーマは一切見えない状態です。

Cookie・sessionStorage・IndexedDB との違い

仕組み特徴よくある使い道
Cookieアクセスのたびにサーバーへ自動で送られる。4KB まで。有効期限を付けられるログイン状態の維持、アクセス解析
localStorageサーバーには送られない。消すまで残る画面の設定、入力途中の下書き、設定のキャッシュ
sessionStoragelocalStorage とほぼ同じだが、タブを閉じると消えるそのタブだけの一時的な状態
IndexedDBインデックスやトランザクションがあり、大量のデータも扱えるオフラインで使えるアプリ

ざっくり言うと、IndexedDB が「ブラウザの中の DB」、localStorage は「設定ファイルや小さなキャッシュ」くらいの位置づけです。

有効期限はない(でも消えることはある)

localStorage には有効期限がありません。ただし、次のような場面では消えます。

場面説明
閲覧データの削除「Cookie と他のサイトデータ」を削除すると一緒に消える
閉じるときに自動で削除する設定Chrome の「すべてのウィンドウを閉じたときにサイトデータを削除する」、Edge の「閉じるときに閲覧データをクリアする」がオンだと、閉じるたびに消える
掃除ソフトブラウザのデータを消すものがある
シークレットウィンドウウィンドウを閉じると消える
PC の買い替え・プロフィールの削除ブラウザの同期機能は localStorage を引き継がない

DB で言えば「TTL はないけれど、バックアップもレプリケーションもなく、利用者が誤って TRUNCATE できるテーブル」です。大事なデータを置くなら、別の場所にバックアップが必要です。

保存場所と中身の見方

実際のファイルの場所
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Local Storage\leveldb\
%LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Local Storage\leveldb\

中身は LevelDB という形式で、ブラウザが管理しています(直接開いて読むものではありません)。

開発者ツールで見る
  • 見たいサイトを開いて F12 →「Application(アプリケーション)」→「Storage」→「Local storage」→ サイトのアドレス

コンソールで中身を一覧表示する

F12 →「Console」に貼り付けて実行します。

console.table(Object.keys(localStorage).map(k => ({
  key: k,
  length: localStorage.getItem(k).length,
  value: localStorage.getItem(k).slice(0, 80)
})));

※ Chrome では初めて貼り付けるときに警告が出るので、案内に従って allow pasting と入力してから貼り付けます。

基本の操作
localStorage.setItem('theme', 'dark');   // 保存
localStorage.getItem('theme');           // 読み込み → "dark"
localStorage.removeItem('theme');        // 1 件削除
localStorage.clear();                    // このサイトの分を全部削除(注意)

// オブジェクトは JSON にして保存する
localStorage.setItem('user', JSON.stringify({ id: 1, name: 'test' }));
JSON.parse(localStorage.getItem('user'));

注意点

  • 平文で保存される。開発者ツールで誰でも見られる
  • 同じオリジンのスクリプトなら何でも読める(XSS で読まれる)。パスワードやトークンなどの秘密は入れない
  • 容量は約 5〜10MB。大きなデータは IndexedDB へ
  • 読み書きは同期処理。大きなデータを何度も読み書きすると画面が止まる
  • 保存する形式を変えるときは、キーに版(app-data-v1 など)を付けておくと移行しやすい。DB のテーブル定義の変更と同じ考え方
スポンサーリンク
タイトルとURLをコピーしました