アプリケーションキャッシュとは?
■アプリケーションキャッシュについて
アプリケーションキャッシュは、HTML5 世代の API です。
http://www.w3.org/TR/html5/browsers.html#offline (Offline Web applications)
http://www.w3.org/TR/html5/browsers.html#application-cache-api (Application cache)
■アプリケーションキャッシュの動作について
オフラインの状態でも動作できるようになります。
ゲームや、アプリケーション等に最適です。
HTML、JavaScript、スタイルシート、画像、サウンドなどの任意のリソースファイルを、ローカルにキャッシュさせる事ができます。
これにより、転送量の削減に繋がるかもしれません。
共通素材の転送量を削減したい場合、通常のキャッシュを利用した方が簡単です。
■通常のキャッシュとの違い
アプリケーションキャッシュは、極めて強い強制力があります。
オンライン状態だったとしても、必ずキャッシュを利用します。
スーパーリロードを行ったとしても、必ずキャッシュを利用します。
■アプリケーションキャッシュに対応しているか調べる
window.applicationCache が真であるか比較します。
Internet Explorer 9 以前では利用できません。
アプリケーションキャッシュに対応しているか調べる
// アプリケーションキャッシュに対応している
if(window.applicationCache){
alert("アプリケーションキャッシュに対応している");
}else{
alert("アプリケーションキャッシュに対応していない");
}
■ ApplicationCache オブジェクトを取得する
ApplicationCache オブジェクトを取得する
// ApplicationCache に対応している
if(window.applicationCache){
// ApplicationCache オブジェクトを取得する
var app_cache = window.applicationCache;
// 出力テスト
console.log(app_cache);
}
マニフェストファイルについて
■マニフェストファイルについて
キャッシュの対象とする、リソースファイル名を指定する事ができます。
■マニフェストファイルを用意する
テキストファイルを用意します。
拡張子は、「.appcache」を指定します。
文字コードは UTF-8 を使用します。
■マニフェストファイルの書式について
■1行目の表記について
1行目に "CACHE MANIFEST" という文字列を記述します。
テキストファイル「my.appcache」を用意して1行目にシンタックス "CACHE MANIFEST" を記述する
CACHE MANIFEST
■コメントについて
コメントを記述したい場合は、'#' を行の先頭に追加します。
コメントを記述する
CACHE MANIFEST
# ------------------------------------
# ~コメントです~
# ------------------------------------
■セクションについて
次にセクションを記述します。セクションには以下の種類があります。
セクション名 | 解説 |
CACHE: | キャッシュしたいファイルを指定します。 |
NETWORK: | オンラインホワイトリストを指定します。 |
FALLBACK: | アクセスに失敗した場合、かわりに使用するファイルを指定します。 |
SETTINGS: | キャッシュモードを設定します。 |
■マニフェストファイルの記述例
マニフェストファイルの記述例
CACHE MANIFEST
# ------------------------------------------------------------
# バージョン情報(リソースを更新する場合、必ず値を変更する)
# ------------------------------------------------------------
#VERSION: 1.0.0
# ------------------------------------------------------------
# キャッシュしたいリソース
# ------------------------------------------------------------
CACHE:
./test.html
./script/test.js
./css/test.css
# ------------------------------------------------------------
# オンラインホワイトリスト(ここでマッチするリソースのみ、オンラインアクセス可能)
# ------------------------------------------------------------
NETWORK:
./test.cgi
./cgi-bin/*
# ------------------------------------------------------------
# アクセスに失敗した場合にかわりに使用するリソース
# ------------------------------------------------------------
FALLBACK:
./online.png ./error.png
# ------------------------------------------------------------
# アプリケーションキャッシュの設定
# ------------------------------------------------------------
SETTINGS:
fast
■コメントのバージョン表記について
こちらで解説しています。
■CACHE セクションについて
キャッシュしたいファイルを指定します。
以下の書式を、必要な数だけ記述します。
『対象ファイル名』+『改行』
指定したファイルは、初回アクセス時に自動的にダウンロードされ、ローカルに保存されます。
■NETWORK セクションについて
オンラインホワイトリストを指定します。
ここでマッチするファイルのみが、オンラインアクセス可能となります。
CACHE セクションにも登録している場合、キャッシュが優先されます。
以下の書式を、必要な数だけ記述します。
『対象ファイル名』+『改行』
アスタリスク * の表記も可能です。
大抵の場合、『 * 』の指定だけで十分でしょう。
どのセクションにも該当しないファイルは、常に 404 エラーが発生する状態に陥ります。
■FALLBACK セクションについて
アクセスに失敗した場合、かわりに使用するファイルを指定します。
以下の書式を、必要な数だけ記述します。
『対象ファイル名』+『空白』+『代替ファイル名』+『改行』
『代替ファイル名』に指定したファイルは、キャッシュの対象となります。
『対象ファイル名』を、NETWORK セクションにも登録していると動作しません。
ただし、アスタリスク表記とマッチするなら、問題ありません。
■SETTINGS セクションについて
キャッシュモードを指定します。
デフォルトは、fast です。
"prefer-online" は、ほどんどのブラウザで未対応?です。
定数 | 解説 |
fast | 必ずアプリケーションキャッシュを利用する。 |
prefer-online | オフラインの場合に限って、アプリケーションキャッシュを利用する。 |
■マニフェストファイルのコンテンツタイプを設定する
マニフェストファイルのコンテンツタイプは「text/cache-manifest」です。
それ以外を指定した場合、アプリケーションキャッシュは動作しません。
■ .htaccess ファイルを使用する
拡張子「.appcache」のコンテンツタイプを「text/cache-manifest」に変更する
AddType text/cache-manifest .appcache
■CGI から、マニフェストファイルを出力する
Perl を使用して、text/cache-manifest を出力する
#!/usr/local/bin/perl
# Content-type を出力
print "Content-type:text/cache-manifest\n";
# 改行のみでヘッダの終了
print "\n";
# text/cache-manifest をヒアドキュメントで出力
print << "EOF";
CACHE MANIFEST
# ------------------------------------------------------------
# バージョン情報
# ------------------------------------------------------------
#VERSION: 1.0.0
# ------------------------------------------------------------
# キャッシュしたいリソース
# ------------------------------------------------------------
CACHE:
test.html
EOF
# ---
PHP を使用して、text/cache-manifest を出力する
<?php
# Content-type を出力
header("Content-type:text/cache-manifest");
# text/cache-manifest をヒアドキュメントで出力
print <<<EOF
CACHE MANIFEST
# ------------------------------------------------------------
# バージョン情報
# ------------------------------------------------------------
#VERSION: 1.0.0
# ------------------------------------------------------------
# キャッシュしたいリソース
# ------------------------------------------------------------
CACHE:
test.html
EOF;
?>
Ruby を使用して、text/cache-manifest を出力する
#!/usr/local/bin/ruby
# Content-type を出力
print "Content-Type: text/cache-manifest\n"
# 改行のみでヘッダの終了
print "\n"
# text/cache-manifest をヒアドキュメントで出力
print <<EOF
CACHE MANIFEST
# ------------------------------------------------------------
# バージョン情報
# ------------------------------------------------------------
#VERSION: 1.0.0
# ------------------------------------------------------------
# キャッシュしたいリソース
# ------------------------------------------------------------
CACHE:
test.html
EOF
Python を使用して、text/cache-manifest を出力する(文字コードを UTF-8 とする)
#!/usr/local/bin/python
# coding: utf-8
# ライブラリをロード
import sys
# Content-type を出力
sys.stdout.write("Content-Type: text/cache-manifest\n\n")
# text/cache-manifest をトリプルクォートで囲んで出力
sys.stdout.write("""CACHE MANIFEST
# ------------------------------------------------------------
# バージョン情報
# ------------------------------------------------------------
#VERSION: 1.0.0
# ------------------------------------------------------------
# キャッシュしたいリソース
# ------------------------------------------------------------
CACHE:
test.html
""")
■ HTML 側にマニフェストファイルを指定する
<HTML> 要素の manifest 属性を使用します。
manifest 属性に、マニフェストファイルまでのアドレスを指定します。
manifest 属性を記述した HTML ファイルは、キャッシュの対象となります。
HTML タグにマニフェストファイルを指定する
<!DOCTYPE html>
<html manifest="./my.appcache">
<body></body>
</html>
サーバーのリソースを更新する
■サーバーのリソースを更新する
■必要な手続きについて
リソースを更新する場合、必ずマニフェストファイルを変更する必要があります。
ブラウザは、マニフェストファイルに変更があった場合に限って、サーバーが更新されたと判別します。
マニフェストファイルの更新を怠った場合、ブラウザはいつまでも古いローカルキャッシュを使い続けます。
■マニフェストファイルを変更する
コメント部分に「バージョン」「タイムスタンプ」などの情報を記述します。
アップデートするたびに、これらの情報を書き換えるといいでしょう。
ローカルのキャッシュを更新する
■アプリケーションキャッシュの流れについて
1.一回目のアクセス(初回)
初回は、マニフェストファイルは考慮されません。
すべてのリソースファイルを、サーバーから読み込みます。
マニフェストで指定されているファイルは、ローカルにキャッシュされます。
2.サーバーのリソースを更新する
こちらで解説しています。
3.二回目のアクセス(サーバー更新後)
この時点では、必ず古いキャッシュで動作します。
ダウンロードが完了しても、コンテンツは古いバージョンのまま、動作し続けます。
4.三回目のアクセス(ダウンロード完了後)
ダウンロード完了後に、リロードすると、新しいキャッシュで動作します。
サーバーの更新を反映させるには、最低でも 2 回リロードしなければなりません。
■アプリケーションキャッシュの状態を取得する
■アプリケーションキャッシュの状態について
以下の種類があります。
定数 | 数値 | 解説 |
UNCACHED | 0 | リソースをキャッシュしていない状態である |
IDLE | 1 | 必要な処理は無く、待機状態である |
CHECKING | 2 | 更新データが存在するかチェック中である |
DOWNLOADING | 3 | 更新を検出したので更新データをダウンロード中である |
UPDATEREADY | 4 | 更新データをダウンロード済みであり、キャッシュの更新が可能である |
OBSOLETE | 5 | マニフェストファイルへのアクセスに失敗したので、アプリケーションキャッシュを削除した状態である |
■アプリケーションキャッシュの状態を取得する
status プロパティを使用します。
アプリケーションキャッシュの状態を出力する
// ブラウザがアプリケーションキャッシュに対応している
if(window.applicationCache){
// ------------------------------------------------------------
// 60 fps 間隔で実行する
// ------------------------------------------------------------
setInterval(function (){
// アプリケーションキャッシュの状態を取得する
var status = applicationCache.status;
switch(status){
case applicationCache.UNCACHED:
console.log("リソースをキャッシュしていない状態である");
break;
case applicationCache.IDLE:
console.log("必要な処理は無く、待機状態である");
break;
case applicationCache.CHECKING:
console.log("更新データが存在するかチェック中である");
break;
case applicationCache.DOWNLOADING:
console.log("更新を検出したので更新データをダウンロード中である");
break;
case applicationCache.UPDATEREADY:
console.log("更新データをダウンロード済みであり、キャッシュの更新が可能である");
break;
case applicationCache.OBSOLETE:
console.log("マニフェストファイルへのアクセスに失敗したので、アプリケーションキャッシュを削除した状態である");
break;
}
},1000/60);
}
■アプリケーションキャッシュのイベントについて
以下の種類があります。
イベント名 | 型 | 解説 |
onchecking | Event | 更新データが存在するかチェック中である |
ondownloading | Event | 更新を検出したので更新データをダウンロード中である |
onprogress | ProgressEvent | 更新データのダウンロードの進捗状況(得られる情報はファイルの個数) |
oncached | Event | リソースのキャッシュに成功した(初回のみ) |
onnoupdate | Event | 更新データが存在するかチェック後、更新データは見つからなかった |
onupdateready | Event | 更新データをダウンロード済みであり、キャッシュの更新が可能である |
onerror | Event | エラーが発生した |
onobsolete | Event | マニフェストファイルへのアクセスに失敗したので、アプリケーションキャッシュを削除した |
アプリケーションキャッシュの状態を出力する
// ブラウザがアプリケーションキャッシュに対応している
if(window.applicationCache){
applicationCache.addEventListener( "checking" , function (e){
console.log("更新データが存在するかチェック中である");
});
applicationCache.addEventListener( "downloading" , function (e){
console.log("更新を検出したので更新データをダウンロード中である");
});
applicationCache.addEventListener( "progress" , function (e){
console.log("更新データのダウンロードの進捗状況 (loaded:" + e.loaded + " total:" + e.total + ")");
});
applicationCache.addEventListener( "cached" , function (e){
console.log("リソースのキャッシュに成功した(初回のみ)");
});
applicationCache.addEventListener( "noupdate" , function (e){
console.log("更新データが存在するかチェック後、更新データは見つからなかった");
});
applicationCache.addEventListener( "updateready" , function (e){
console.log("更新データをダウンロード済みであり、キャッシュの更新が可能である");
});
applicationCache.addEventListener( "error" , function (e){
console.log("エラーが発生した");
});
applicationCache.addEventListener( "obsolete" , function (e){
console.log("マニフェストファイルへのアクセスに失敗したので、アプリケーションキャッシュを削除した");
});
}
■サーバーが更新されたか調べる
update() メソッドを使用します。
コンテンツによっては、呼び出す必要はありません。
更新チェックは、ページを開いた瞬間に、1度だけ自動的に実行されます。
長時間動作するコンテンツにて、呼び出すといいでしょう。
ApplicationCache.update ( ) :Void
引数 | Void | なし |
戻り値 | Void | なし |
30 分に 1 回の時間隔で、更新をチェックする
// ------------------------------------------------------------
// 一定の時間隔で実行する
// ------------------------------------------------------------
setInterval(function (){
// ------------------------------------------------------------
// サーバのリソースが更新されたかチェックする
// ------------------------------------------------------------
applicationCache.update();
},1000 * 60 * 30);
■リソースの更新を検出した場合
status が DOWNLOADING に変化します。
リソースファイルのダウンロードが、自動的に開始されます。
■ダウンロードが完了した場合
■キャッシュを最新のデータに差し替える
ApplicationCache.update ( ) :Void
引数 | Void | なし |
戻り値 | Void | なし |
キャッシュの更新が可能であるか調べて、キャッシュを更新する
// ------------------------------------------------------------
// 「更新データをダウンロード済み」で「キャッシュの更新が可能」なときに実行されるイベント
// ------------------------------------------------------------
applicationCache.addEventListener( "updateready" , function (e){
// ------------------------------------------------------------
// キャッシュを最新のデータに差し替える
// ------------------------------------------------------------
applicationCache.swapCache();
});
■キャッシュを差し替えた場合
画像などが、自動的に差し替わる訳ではありません。
現在のコンテンツは、古いまま動き続けます。
■リアルタイム更新を実装する
JavaScript でリソースの読み込みを試みると、最新のリソースにアクセスできるようになります。(XHR 通信)
新しいリソースを、手動的に再読み込みし、コンテンツに反映させます。
■リアルタイム更新の実装が難しい場合
リアルタイム更新を実装しない場合、ユーザーにリロードを促します。
この場合、swapCache() メソッドを呼び出す必要はありません。
リロード後は、最新のキャッシュで動作します。
キャッシュの更新が可能であるか調べて、ユーザーにページのリロードを促す
// ------------------------------------------------------------
// 「更新データをダウンロード済み」で「キャッシュの更新が可能」なときに実行されるイベント
// ------------------------------------------------------------
applicationCache.addEventListener( "updateready" , function (e){
// ------------------------------------------------------------
// 「確認ダイアログを表示する
// ------------------------------------------------------------
var result = confirm("最新のアプリケーションを利用できます。\nページをリロードしますか?");
// YES が押された
if(result){
// ページをリロードする
location.reload();
}
});
■更新データのダウンロードを中止する
abort() メソッドを使用します。
ApplicationCache.abort ( ) :Void
引数 | Void | なし |
戻り値 | Void | なし |
■アプリケーションキャッシュの削除について
JavaScript から、アプリケーションキャッシュを削除する事はできません。
マニフェストファイルへのリクエストが失敗した場合、アプリケーションキャッシュは削除されます。(404 エラーなど)
ユーザーはブラウザの設定から、アプリケーションキャッシュを削除できます。