IE10 での HTML5 History
本記事は、マイクロソフト本社の IE チームのブログ から記事を抜粋し、翻訳したものです。
【元記事】HTML5 History in IE102011/11/1 7:42 AM
高速かつ高機能なサイトの構築は、多くの Web 開発者が直面している課題の 1 つです。
ユーザーがリンクをクリックするたびに新しいページを読み込んでいると遅くなりますし、すべてのコンテンツを動的に取得すると、[戻る] ボタンがほとんど機能しなくなります。ハッシュを操作するのも悪くありませんが、それでも理想的とは言えません。
Windows Developer Preview に含まれている Internet Explorer 10 では、HTML5 History のサポートが追加され、この問題が解消されています。
pushState、replaceState、popstate の各 API によって、[戻る] ボタンの動作や、動的コンテンツの場合にユーザーに表示される URL を細かく制御できます。これらの API を組み合わせると、使いやすさを犠牲にすることなく、サイトのパフォーマンスを向上させることができます。
HTML5 の History API についてまだよく知らない場合は、pushState を、別のページへの移動を動的に行うものと考えてください。
同様に、replaceState は location.replace とほぼ同じものです。違いは、これらの API ではセッション履歴の更新時にページではなく状態を保存することにより、現在のページが保持されるということです。pushState と replaceState のどちらも、データ オブジェクト、タイトル、オプション URL の 3 つのパラメーターを使用します。
history.pushState(data, title, url);
history.replaceState(data, title, url);
pushState と replaceState の title パラメーターは、IE10 を含む、ほとんどのブラウザーで無視されることに注意してください。この情報は、指定したままにしておいてもかまいません。ブラウザーは、将来的に、履歴の UI の一部としてこの情報を表示する可能性があります。
カスタム URL の設定
pushState および replaceState の URL パラメーターは、移動することなくページの URL を更新するために使用します。たとえば、"http://www.contoso.com/index.html" を読み込んだとします。ハッシュ変更を使用しても、URL に付加する以上のことはできません。
//"http://www.contoso.com/about.html"に変更
history.pushState(null, "About", "/about.html");
しかし、pushState および replaceState の使用では、実際に移動することなく、現在のサイト上のまったく違うページを指定できます。
history.pushState("about.html", "About", "/about.html");
プロトコル、ホスト名、ポートは現在の URL と同じものにしますが、パス、クエリ、フラグメントはカスタマイズできます。これにより、動的な状態と、サーバーから容易に取得できる URL とを関連付けることができ、スクリプトが無効の場合でも機能します。最終的には、ユーザー エクスペリエンスを変えることなく、ページごとに変化するデータだけを動的に取得して表示できるようになります。
保存した状態の復元
履歴を使って移動した後 (たとえば、ユーザーが [戻る] ボタンを押した場合など)、またはページを再読み込みした後には、状態を復元することが推奨されます。状態の復元は、popstate イベントをリッスンすることで実現できます。popstate イベントは、履歴を使っての移動の結果として状態が変化したときに発生します。このときに、移動先の状態を示すデータ オブジェクトを history.state から取得できます。ページを再読み込みした場合、popstate イベントは発生しませんが、history.state は読み込み中や読み込み後など、いつでもアクセスすることができます。そのため、次のようなコードを使用すると、必要なタイミングで状態を復元できます。
function init() {
/* ... */
// ページの読み込みや再読み込みを処理
loadState();
// 履歴を使っての移動 ([戻る] ボタンなど) をリッスン
window.addEventListener("popstate", loadState, false);
}
function loadState() {
// そのときの状態を表すデータを取得して、復元できるようにする
var state = history.state;
/* ... */
}
init();
複雑な動的データの保存
状態に保存されるデータ オブジェクトは、文字列だけではありません。カスタムの JavaScript オブジェクトや一部のネイティブな型 (ImageData など) も使用できます。指定されたデータは、構造化クローン アルゴリズムを使用して保存されます。これにより、循環や同じオブジェクトへの多重参照など、複雑な関係が保持されます。このシンプルなデモで示すように、複雑なオブジェクトも簡単に保存して復元できます。このデモでは、キャンバスのスナップショットをキャプチャし、次のようなコードを使用して、やり直し用のスタックを作成しています。
function init() {
/* ... */
// ページの読み込みや再読み込みを処理
loadState();
// 履歴を使っての移動 ([戻る] ボタンなど) をリッスン
window.addEventListener("popstate", loadState, false);
}
/* ... */
function stopDrawing() {
// 現在の状態のスナップショットを ImageData インスタンスとして取得
var state = context.getImageData(0, 0, canvas.width, canvas.height);
history.pushState(state, "");
/* ... */
}
function loadState() {
// そのときの状態を表すデータを取得して、復元できるようにする
var state = history.state;
/* ... */
if (state) {
// ImageData として保存した状態をキャンバスに復元
context.putImageData(state, 0, 0);
}
}
過去の変更を 1 つ 1 つすべて残すのではなく、現在の状態を保持するようにこの例を変更するには、pushState ではなく、replaceState を使用します。
サイズに関する考慮事項
HTML5 History では注意しないと、大量のデータをスタックに保持することになりがちです。たとえば、上記のやり直し機能のデモでは、1 つの状態ごとに保存されるデータは 0.5 MB 以下ですが、キャンバスが大きくなればデータ量は増加します。このデータは、関連する状態のエントリがセッション履歴に存在する間 (場合によっては、ユーザーがサイトを離れた後も) メモリを消費し続けます。保存するデータが多くなると、ブラウザーは領域を確保するためにエントリを消去するタイミングを早くします。さらに、ブラウザーによっては、pushState や replaceState の 1 回の呼び出しで保存できるデータ量の制限が厳しいこともあります。
クロス ブラウザーに関する考慮事項
これまでと同じですが、ブラウザー間のサポート状況の違いには機能検出を使用して対処します。HTML5 履歴の大半はイベントとプロパティであるため、実際に検出が必要な新しい部分は、pushState と replaceState の呼び出しだけです。
function stopDrawing() {
var state = context.getImageData(0, 0, canvas.width, canvas.height);
if (history.pushState)
history.pushState(state, "");
/* ... */
}
このような検出を行っておけば、少なくとも古いブラウザーでスクリプトがエラーになることはありません。状況によっては、最初はページ全体の移動を使用しておき、HTML5 History がサポートされたら動的コンテンツにアップグレードする場合もあります。あるいは、History フレームワークや polyfill を使用して、[戻る] ボタンの機能を確保することもできます。ただし、この場合、すべてが実現できるわけではないことに注意してください。たとえば、URL のパスやクエリ部分の動的な制御は、pushState や replaceState を使わなければ実現できません。
一部のブラウザーでは、HTML5 History の初期の草案がサポートされていることに注意してください。現在の草案とは、次の大きな 2 つの相違があります。
- popstate イベントが、ページの読み込み中にも発生する
- history.state プロパティが存在しない
このようなブラウザーをサポートする場合は、popstate イベントを使用せずに状態情報を読み取る方法に戻ることができます。
まとめ
全体として、HTML5 History の API を使用すると、応答性が高く便利な Web サイトを非常に柔軟に構築できます。従来のブラウザーへの配慮は必要ですが、これらの API を使用することで大きな効果を得ることは可能です。Windows Developer Preview の IE10 でぜひご自身のサイトを試し、Connect からフィードバックをお寄せください。
—Tony Ross (プログラム マネージャー、Internet Explorer)