HTML5 オフライン Web アプリケーションとキャッシュマニフェスト
Web アプリケーションは、インターネットの常時接続性に支えられ、ここ10数年で急速に普及しました。
サーバー側でスクリプトを書き換えれば、そこに接続するクライアントにもその変更が容易に適用できるなど、運用の利便性もあって、 今でもインターネット、イントラネットどちら向けにも大変人気です。
ところが、モバイルアプリの開発となると少々厄介なことが発生します。
ここでは HTML5 で導入されたオフライン Web アプリケーションと、それを支えるキャッシュマニフェストについて説明します。
HTML5 のオフライン機能とは
携帯端末は、当然ながら地理的な移動に "携帯" するものですから、ネットワークへの接続可能性が、 デスクトップ PC の場合と比べて圧倒的に低くなります。
ひとことでいえば、「ネットがチョイチョイ切れる」わけです。
従来の Web アプリケーションでは、「ネットワークに接続できません」というブラウザのエラーメッセージが表示されて終了でしたが、 HTML5 ではもう少し気が利いています。
指定したコンテンツを強力にキャッシュしておき、ネットワークが切れた場合にも「ネットワークに接続できません」 といったエラーを表示しないようにできます。
例えば 「page1.html はキャッシュする」 と指定すれば、一度ダウンロードしてキャッシュしておいた page1.html を次回から利用します。
また、 「myapi.php はキャッシュしない」ということも指定できるので、API の呼び出しなど、毎回新しい HTTP リクエストを送って欲しいものも指定できます。
さらに「image1.png が使えなかった場合には offline.png を使う」という指定もできます。これをフォールバックといいます。
では具体的にどのように実装するかみてみましょう。
キャッシュマニフェストの指定
どのファイルをキャッシュし、どれをキャッシュしないか指定するファイルのことをキャッシュマニフェスト (cache manifest) といいます。
キャッシュマニフェストは html タグの manifest 属性として指定します。
<!doctype html>
<html manifest="foo.manifest">
<head>
...
ここで foo.manifest という名前のファイルをキャッシュマニフェストとして指定しています。
ちなみに、キャッシュマニフェストの MIME タイプは text/cache-manifest とします。
キャッシュマニフェストの書き方
キャッシュマニフェストは次のように書きます。
CACHE MANIFEST file1.html file2.html ... NETWORK: foo.cgi bar.cgi ... FALLBACK: img1.png alt1.png img2.png alt2.png ...
ファイルは "CACHE MANIFEST" で始まり、基本的なセクションは三つ。CACHE MANIFEST に続きファイル名が記載される箇所、 NETWORK セクション、FALLBACK セクションです。一番目の箇所は明示的に書くと "CACHE:" となるところですが、書かなくて OK です。
それぞれ、「キャッシュするファイル」(CACHE:)「キャッシュしないファイル」(NETWORK:)「オフライン時の代替ファイルの指定」(FALLBACK:) を表しています。
キャッシュの更新チェックと更新
オフラインアプリケーションのキャッシュは強力です。 明示的にキャッシュが更新されたかチェックする仕組みを実装しないと、更新を全くチェックしないブラウザもあるようです。
window.applicationCache に次のように "updateready" イベントのイベントリスナーを設定した上で、 キャッシュの update メソッドを呼び出します。こうすると、キャッシュマニフェストが更新されている場合それを検出することが可能になります。
var cache = window.applicationCache;
cache.addEventListener('updateready',function(){
if(cache.status === 4){
if(confirm('新しいバージョンが利用可能です')){
cache.swapCache();
location.reload();
}
}
});
cache.update();
キャッシュを入れ替える場合は swapCache メソッドを呼び出します。
Chrome での動作確認
Chrome では特定のページを呼び出したときに、一度キャッシュのチェックを行っていました。
そこでページのロードイベント時に次のように window.applicationCache に "updateready" イベントのイベントリスナーをセットします。
$(document).ready(function(){
if(window.applicationCache){
var cache = window.applicationCache;
cache.addEventListener('updateready',function(){
if(cache.status === 4){
if(confirm('新しいバージョンが利用可能です')){
cache.swapCache();
location.reload();
}
}
});
}
});
URL をたたく度にデベロッパーコンソールで、"Checking event" が発生している事が確認できました。
Network の状況を見るとキャッシュを利用しているときは Size が "(from cache)" となっています。
キャッシュマニフェストを更新すると、UpdateReady event が発生。それのハンドラにて、 ここでは更新するかどうかを聞くダイアログを表示しています。