JavaScript プログラミング講座

 

アプリケーションキャッシュとは?

 


■アプリケーションキャッシュについて

 
アプリケーションキャッシュは、HTML5 世代の API です。
 
 
■アプリケーションキャッシュの動作について
 
オフラインの状態でも動作できるようになります。
 
ゲームや、アプリケーション等に最適です。
 
HTML、JavaScript、スタイルシート、画像、サウンドなどの任意のリソースファイルを、ローカルにキャッシュさせる事ができます。
 
これにより、転送量の削減に繋がるかもしれません。
 
共通素材の転送量を削減したい場合、通常のキャッシュを利用した方が簡単です。
 
■通常のキャッシュとの違い
 
アプリケーションキャッシュは、極めて強い強制力があります。
 
オンライン状態だったとしても、必ずキャッシュを利用します。
 
スーパーリロードを行ったとしても、必ずキャッシュを利用します。
 

■アプリケーションキャッシュに対応しているか調べる

 
window.applicationCache が真であるか比較します。
 
Internet Explorer 9 以前では利用できません。
 
アプリケーションキャッシュに対応しているか調べる

// アプリケーションキャッシュに対応している
if(window.applicationCache){

	alert("アプリケーションキャッシュに対応している");

}else{

	alert("アプリケーションキャッシュに対応していない");

}
 

■ ApplicationCache オブジェクトを取得する


window.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);
 
■リソースの更新を検出した場合
 
statusDOWNLOADING に変化します。
 
リソースファイルのダウンロードが、自動的に開始されます。
 
■ダウンロードが完了した場合
 
statusUPDATEREADY に変化します。
 
キャッシュを最新のデータに差し替える事ができます。
 

■キャッシュを最新のデータに差し替える

 
swapCache() メソッドを使用します。
 
statusUPDATEREADY である必要があります。
 
ApplicationCache.update ( ) :Void
引数 Voidなし
戻り値 Voidなし
 
キャッシュの更新が可能であるか調べて、キャッシュを更新する

// ------------------------------------------------------------
// 「更新データをダウンロード済み」で「キャッシュの更新が可能」なときに実行されるイベント
// ------------------------------------------------------------
applicationCache.addEventListener( "updateready" , function (e){

	// ------------------------------------------------------------
	// キャッシュを最新のデータに差し替える
	// ------------------------------------------------------------
	applicationCache.swapCache();

});
 
■キャッシュを差し替えた場合
 
画像などが、自動的に差し替わる訳ではありません。
 
現在のコンテンツは、古いまま動き続けます。
 
■リアルタイム更新を実装する
 
JavaScript でリソースの読み込みを試みると、最新のリソースにアクセスできるようになります。XHR 通信
 
新しいリソースを、手動的に再読み込みし、コンテンツに反映させます。
 
■リアルタイム更新の実装が難しい場合
 
リアルタイム更新を実装しない場合、ユーザーにリロードを促します。
 
確認ダイアログを表示するには、confirm() メソッドを使用します。
 
ページをリロードするには、location.reload() メソッドを使用します。
 
この場合、swapCache() メソッドを呼び出す必要はありません。
 
リロード後は、最新のキャッシュで動作します。
 
キャッシュの更新が可能であるか調べて、ユーザーにページのリロードを促す

// ------------------------------------------------------------
// 「更新データをダウンロード済み」で「キャッシュの更新が可能」なときに実行されるイベント
// ------------------------------------------------------------
applicationCache.addEventListener( "updateready" , function (e){

	// ------------------------------------------------------------
	// 「確認ダイアログを表示する
	// ------------------------------------------------------------
	var result = confirm("最新のアプリケーションを利用できます。\nページをリロードしますか?");

	// YES が押された
	if(result){

		// ページをリロードする
		location.reload();

	}

});
 

■更新データのダウンロードを中止する

 
abort() メソッドを使用します。
 
ApplicationCache.abort ( ) :Void
引数 Voidなし
戻り値 Voidなし
 

■アプリケーションキャッシュの削除について

 
JavaScript から、アプリケーションキャッシュを削除する事はできません。
 
マニフェストファイルへのリクエストが失敗した場合、アプリケーションキャッシュは削除されます。(404 エラーなど)
 
ユーザーはブラウザの設定から、アプリケーションキャッシュを削除できます。