Web Storage について

ひさしぶりのエントリになります。JavaScript Advent Calendar 2010 の24日担当です。
この Advent Calendar では、12月1日からクリスマスの12月25日まで1日ずつ持ち回りでblogに書くことになっています。お題に"JavaScript"とあるように、blogは、JavaScriptに関するものになります。他の方々も面白いことを色々を書いておられますので、是非読んでみてください。


さて、何やら世間はクリスマスイブで盛り上がっていますが、仕事で缶詰の私には関係ありませんので(もちろん仕事がなくても関係ありませんが…)、今回は、HTML5 の API のひとつである、Web Storage について紹介したいと思います。
割と初心者向けの内容になります。


Web Storage とは
Web Storage は、データをブラウザ上に永続的に保持するための仕様で、キーと値をセットとした連想配列のようにデータを保持します。仕様では、localStorage と sessionStorage に分かれており、それぞれ以下の特徴があります。いずれも、オリジン(プロトコル、ドメイン、ポート)ごとに保存されます。

  • localStorage

ブラウザを閉じても保持される。同一オリジンであれば、ウィンドウ間でも共有できる。
 

  • sessionStorage

ブラウザを閉じると消去される。ウィンドウごとのセッションで有効。


仕様書: W3C Web Storage Editor's Draft
http://dev.w3.org/html5/webstorage/


この Web Storage ですが、モダンなブラウザでは既に対応済みなので、他のHTML5のAPIの中では、比較的、安心して使うことができます。特にIE8が対応していることが大きいでしょう。(IE6などのブラウザでもGearsで対応できるようです)

サポートブラウザ

IE 8 Firefox 3.6 Chrome 7 Safari 5 Opera 10


localStorageとsessionStorageのAPIは共通で、以下のメソッドを介して利用します。

API一覧
localStorage/sessionStorage

メソッド 説明
length ストレージの長さを返す。
key(n) n番目のkeyを返す。
getItem(key) keyに対応する値を返す。
setItem(key, value) keyに対応するvalueを保存する。
removeItem(key) keyに対応する値を削除する。
clear() ストレージを消去する。


簡単な使い方

// データを保存する。
localStorage.setItem("hoge", "test");

// データを取り出す。
localStorage.getItem("hoge");
> "test"

// 次のように記述することもできます
// データを保存する。
localStorage.hoge2 = "test2";
localStorage["hoge3"] = "test3";

// データを取り出す。
localStorage.hoge2;
> "test2"

localStorage["hoge3"];
> "test3"

//保存されている値をすべて表示する
for ( var i = 0, len = localStorage.length; i < len; i++ ) {
  alert(localStorage.getItem(localStorage.key(i));
}


注意事項として、Web Storage で保存できる値は、仕様上は Any となっており、JSオブジェクトでも登録できるはずですが、残念ながらまだ実装されているブラウザはなく、すべて文字列として保存する形になっています。

// 配列を保存しても文字列になってしまう
var ary = ["aaa", "bbb"];
localStorage.setItem("hoge", ary);

localStorage.getItem("hoge");
> "aaa,bbb"


そのため、JSオブジェクトを扱いたい場合は、JSON.stringifyとJSON.parseを利用するなどして文字列に変換してから利用することをおすすめします。

// 配列をJSON.stringifyで文字列に変換してから保存
var ary = ["aaa", "bbb"];
localStorage.setItem("hoge", JSON.stringify(ary));

// 取り出した文字列をJSON.parseでJSオブジェクトに変換する
JSON.parse(localStorage.getItem("hoge"));
> ["aaa", "bbb"]


保存できるデータ量
きちんと計測したわけではないので、詳細は省略させて頂きますが、ChromeやSafariは5MB。IE8は10MB程度のようです。Chromeのブラウザ拡張であれば unlimitedStorage オプションを指定することによって制限を解除できます。unlimitedStorageオプションが有効なのはWeb SQL DatabaseとIndexed Databaseのみでした。


クッキーとの違い
以前までの、ブラウザ上でのデータの保持方法として主にクッキーが使われていましたが、クッキーと比べて以下の違いがあります。

  • 通信量の削減

クッキーはリクエストを投げるたびにクッキーの内容をすべてサーバーに送信しているため、トラフィックが増大する。そのため、クッキーに保存するデータ量が多くなればなるほど、サイトが重くなったりするなどの弊害がある。Web Storageは、ローカル内だけで完結するため、余計なトラフィックが増えない。

  • セキュリティの向上

クッキーはローカルで保持しておくべきデータでもリクエストのたびに送信しているため、ネットワークの経路上でデータが漏洩する可能性があった。もちろんWeb Storage でも基本的なアクセシビリティはクッキーと同じで、XSSなどで盗まれる恐れがありますが。
※いずれにせよ、パスワードや個人情報などの機微なデータを保存しないようにするべきです。


その他の注意事項
Web Storage で使う上で注意しておくことは以下の通りです。

  • localStorage の削除

localStorage は、保存期限がないため削除しないでいるとゴミデータが残ってしまいます。使わなくなったデータはきちんと削除するか、そもそもブラウザの起動を跨いで保存する必要がない場合は、sessionStorage を使いましょう。

  • スコープの範囲

Web Storage のスコープはオリジン(プロトコル、ドメイン、ポート)なので、共有サーバーやひとつのドメインで複数のアプリケーションを管理している場合には、データが混在してしまいます。そういった環境で利用するのであれば、衝突しないよう命名規則などに留意することや、全件処理及びクリア処理などに気をつけましょう。


関連するイベント
Web Storage には、StorageEvent というイベントが用意されており、データ更新時などの動きをハンドリングすることができます。


StorageEvent

プロパティ 説明
key 更新されたキー
oldValue 更新前の値
newValue 更新後の値
url 更新されたページのURL
storageArea 更新されたStorage(localStorageまたは、sessionStorage)

// StorageEventを登録
window.addEventListener("storage", function(evt) {
  console.log("old:" + evt.oldValue + "/new:" + evt.newValue);
}, false);

// データ更新
//localStorage.setItem("hoge", "aaa");
localStorage.setItem("hoge", "bbb");
> "old:aaa/new:bbb"


ただ、StorageEventは主に開発版などで実装されており、正式版での実装状況はまちまちになると思われるので、使用する場合は注意してください。

IE 9 beta Firefox 4 beta8 Chrome 9 Webkit nighty Opera 11


活用事例
Web Storage は既にメジャーなサイトでも積極的に活用されています。
以下は、そのうちのサイトの一部です。他にも、こんなところで使ってるよ!など、知ってる方がいらっしゃいましたら教えて頂くと嬉しいです。

タイムライン右側のフォロー、フォロワー部分のHTMLをlocalStorageでキャッシュしています。

おすすめリストなどのページングのページ番号の保持にsessionStorageが使われています。

  • その他ブラウザ拡張等

拡張の設定などにlocalStorageが使われていることが多いです。



おわりに
そろそろ、時間もやばそうなのでこの辺にしておきたいと思います。(24日をオーバーしてしまう!)Web Storage は、現在でも大きな部分から小さいなところまで幅広く使っていける機能ですので、サイトを構築する際には、是非とも検討していただけたら面白いのではないでしょうか。


それでは、Happy Coding!