アプリケーションキャッシュとは?
■アプリケーションキャッシュとは?
Web アプリケーションは、ユーザーの端末がオフラインの状態になると、通常はそのページにアクセスできなくなり、サービスが利用できません。
そこでアプリケーションキャッシュを利用すると、HTML や JavaScript、スタイルシート、画像、サウンド、動画などの「Web アプリケーションの動作に必要なリソースファイル」がローカルに保存されるようになります。
これによりオフラインの状態でも動作させることができます。
また、一度リソースがキャッシュされると、オンラインであったとしてもローカルキャッシュの方を優先的に利用するようになります。
これにより、サーバ側の転送量の節約に繋がるかもしれません。
■アプリケーションキャッシュオブジェクトにアクセスする
window.applicationCache プロパティに、アプリケーションキャッシュオブジェクトが格納されています。
このプロパティが未定義であれば、ブラウザがアプリケーションキャッシュに対応していません。
Internet Explorer 9 は未対応です。
アプリケーションキャッシュオブジェクトにアクセスする
var app_cache = window.applicationCache;
console.log(app_cache);
マニフェストファイルを用意する
■マニフェストファイルを用意する
どのファイルをキャッシュするかなどの情報を記述するために、マニフェストファイルを用意します。
まず、拡張子が、".appcache" となるテキストファイルを用意します。
文字コードは「UTF-8」を使用します。
ここでは「test.appcache」というファイルを作成します。
■マニフェストファイルの書式について
1行目に "CACHE MANIFEST" という文字列を記述します。
テキストファイル「test.appcache」を用意して1行目にシンタックス "CACHE MANIFEST" を記述する
CACHE MANIFEST
コメントを記述したい場合は、'#' を行の先頭に追加します。
コメントを記述する
CACHE MANIFEST
# ------------------------------------
# ~コメントです~
# ------------------------------------
次にセクションを記述します。セクションには以下の種類があります。
| セクション名 | 解説 |
| CACHE: | キャッシュしたいファイルを指定します。ここで指定したファイルは、アクセス時にすべてダウンロードされ、ローカルに保存されます。 |
| NETWORK: | オンラインホワイトリストと呼ばれます。必ずオンラインから情報を取得したいファイルを指定します。ここで指定したファイルはローカルに保存されません。 |
| FALLBACK: | アクセスに失敗した場合、代わりに使用するファイルを指定します。同じファイルを NETWORK にも登録していると動作しません。 |
マニフェストファイルの記述例です。
マニフェストファイルの記述例
CACHE MANIFEST
# ------------------------------------------------------------
# バージョン情報(リソースを更新する場合、必ず値を変更する)
# ------------------------------------------------------------
#VERSION: 1.0.0
# ------------------------------------------------------------
# キャッシュしたいリソース
# ------------------------------------------------------------
CACHE:
test.html
script/test.js
css/test.css
# ------------------------------------------------------------
# 必ずオンラインアクセスを試みるリソース
# ------------------------------------------------------------
NETWORK:
test.cgi
# ------------------------------------------------------------
# アクセスに失敗した場合に代わりに使用するリソース(NETWORK:と両方に指定すると動作しない)
# ------------------------------------------------------------
FALLBACK:
online.png error.png
■コメントのバージョン表記について
ブラウザがすでにキャッシュ済みである場合、サーバ側のリソースファイルを新しく更新したとしても、ブラウザは古いローカルキャッシュに優先的にアクセスを試みようとします。
ブラウザが「サーバのリソースが更新された」と判別する条件は、「マニフェストファイルに変更があった場合」です。
サーバのリソースを更新したい場合は、マニフェストファイルに何らかの変更を必ず行う必要があります。
マニフェストファイルの更新を怠った場合、ブラウザはいつまでも古いローカルキャッシュを使い続けます。
コメント部分に「バージョン」や「タイムスタンプ」などの情報を記述しておいて、アップデートするたびに書き換えるといいでしょう。
■FALLBACK セクションについて
「対象とするリソースファイル名」「空白」「オフライン時に変わりに使用するリソースファイル名」「改行」を連続で記述します。
「対象とするリソースファイル名」が、NETWORK セクションに登録されていると動作しないので注意します。
「オフライン時に変わりに使用するリソースファイル名」に指定したファイルは、キャッシュの対象となります。
■HTML 側にマニフェストファイルを指定する
「HTML タグ」にマニフェストファイルを設定します。
manifest 属性に、マニフェストファイルまでのアドレスを指定します。
manifest 属性を指定した HTML ファイルは、キャッシュの対象となります。
HTML タグにマニフェストファイルを指定する
<html manifest="test.appcache">
<body></body>
</html>
■サーバ側にマニフェストファイルのコンテンツタイプを設定する
HTTP サーバに、「appcache という拡張子であれば、MIMEタイプを「text/cache-manifest」として処理する」ように指定します。
「.htaccess ファイル」が使用できる場合、以下を追加します。
拡張子「.appcache」のファイルであれば、MIMEタイプを「text/cache-manifest」として処理する
AddType text/cache-manifest .appcache
「.htaccess ファイル」が使用できない場合、CGI でマニフェストファイルを返す事もできます。
拡張子は 「.appcache」である必要はありませんが、コンテンツタイプは必ず「text/cache-manifest」である必要があります。
各スクリプトの出力例です。
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
""")
キャッシュを最新の状態にアップデートする
■アプリケーションキャッシュの更新について
ユーザーが、アプリケーションキャッシュ対応のページのリロードを 2 回行うと、自動的にアプリケーションキャッシュは最新のものに更新されます。
自動的にではなく、JavaScript から手動的にキャッシュを最新のものに更新することもできます。
■アプリケーションキャッシュの状態を取得する
アプリケーションキャッシュには、以下の状態が定義されています。
| 定数 | 数値 | 解説 |
| UNCACHED | 0 | リソースをキャッシュしていない状態である |
| IDLE | 1 | 必要な処理は無く、待機状態である |
| CHECKING | 2 | 更新データが存在するかチェック中である |
| DOWNLOADING | 3 | 更新を検出したので更新データをダウンロード中である |
| UPDATEREADY | 4 | 更新データをダウンロード済みであり、キャッシュの更新が可能である |
| OBSOLETE | 5 | マニフェストファイルへのアクセスに失敗したので、アプリケーションキャッシュを削除した状態である |
「アプリケーションキャッシュの状態」を取得するには、status プロパティを使用します。
アプリケーションキャッシュの状態を出力する
// ブラウザがアプリケーションキャッシュに対応している
if(window.applicationCache){
// 60 fps 間隔で実行する
setInterval(function(){
switch(applicationCache.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);
}
また、以下のイベントリスナーに対応しています。
アプリケーションキャッシュの状態を出力する
// ブラウザがアプリケーションキャッシュに対応している
if(window.applicationCache){
applicationCache.addEventListener("error",function(e){
console.log("エラーが発生した");
},false);
applicationCache.addEventListener("cached",function(e){
console.log("リソースのキャッシュに成功した(初回のみ)");
},false);
applicationCache.addEventListener("noupdate",function(e){
console.log("更新データが存在するかチェック後、更新データは見つからなかった");
},false);
applicationCache.addEventListener("downloading",function(e){
console.log("更新を検出したので更新データをダウンロード中である");
},false);
applicationCache.addEventListener("progress",function(e){
console.log("更新データをダウンロードの進捗状況");
},false);
applicationCache.addEventListener("updateready",function(e){
console.log("更新データをダウンロード済みであり、キャッシュの更新が可能である");
},false);
applicationCache.addEventListener("obsolete",function(e){
console.log("マニフェストファイルへのアクセスに失敗したので、アプリケーションキャッシュを削除した状態である");
},false);
}
■サーバのリソースが更新されたか調べる
「サーバのリソースが更新された」と判断する条件は、マニフェストファイルに変化があった場合です。
ページにアクセスした際に、ブラウザは自動で「サーバのリソースが更新されたか」チェックします。
JavaScript から手動的に「サーバのリソースが更新されたか」調べるには、update() メソッドを使用します。
サーバのリソースが更新されたかチェックする
// サーバのリソースが更新されたかチェックする
applicationCache.update();
ブラウザが「サーバのリソースの更新を検出した」場合、自動的にアプリケーションキャッシュの状態が DOWNLOADING に変化し、リソースファイルのダウンロードが開始されます。
リソースファイルのダウンロードが完了すると、自動的にアプリケーションキャッシュの状態が UPDATEREADY に変化し、アプリケーション動作中に、古いキャッシュを最新のリソースと差し替える事できるようになります。
■アプリケーション動作中にキャッシュを更新する
アプリケーションキャッシュの状態が UPDATEREADY である場合、アプリケーション動作中にキャッシュを最新のリソースへと差し替える事ができます。
キャッシュを差し替えるには、swapCache() メソッドを使用します。
swapCache() メソッド呼び出した後で、JavaScript から動的にリソースの読み込みを行うと更新されたファイルにアクセスできます。
キャッシュの更新が可能であるか調べて、キャッシュを更新する
// 「更新データをダウンロード済みであり、キャッシュの更新が可能である」ときに実行されるイベント
applicationCache.addEventListener("updateready",function(e){
// アプリケーション動作中にキャッシュを更新する
applicationCache.swapCache();
},false);
大抵の場合、アプリケーションを動作させつつ最新の状態に更新するのは難しいです。
実装が面倒な場合は、ユーザーにページのリロードを促すといいでしょう。
キャッシュの更新が可能であるか調べて、ユーザーにページのリロードを促す
// 「更新データをダウンロード済みであり、キャッシュの更新が可能である」ときに実行されるイベント
applicationCache.addEventListener("updateready",function(e){
var result = confirm("最新のアプリケーションを利用できます。\nページをリロードしますか?");
// YES が押された
if(result){
// ページをリロードする
location.reload();
}
},false);
