2011年4月19日火曜日

HTML5でiPhone用Webアプリをオフライン対応に

キャッシュマニフェスト」ファイルを作るには
 アプリケーションキャッシュを使うには、Webブラウザにキャッシュしてほしいファイルを知らせる「キャッシュマニフェスト」ファイルを作るところから始めます。
 Webアプリで使っている、JavaScriptのソースコードファイルや画像ファイル、CSSファイルなどのパスを書いておけば、一度ロードされるとアプリケーションキャッシュに格納されて、次回以降はリクエストされなくなります。
 キャッシュマニフェストファイルの中身を見てみましょう。
CACHE MANIFEST
# Version: 7022

CACHE:
/h/MobileView.do?v=1.2.11&lang=ja
/h/images/apple-touch-icon.png?v=1.2.11
/h/iui-0.40/iui.css
/h/iui-0.40/t/default/default-theme.css
/h/iui-0.40/t/default/backButton.png
/h/iui-0.40/t/default/backButtonBack.png
/h/iui-0.40/t/default/backButtonBrdr.png
/h/iui-0.40/t/default/blueButton.png
/h/css/my-iui.css?v=1.2.11
/h/js/prototype.js?v=1.2.11
/h/js/json2.js?v=1.2.11
/h/iui-0.40/iui.js


【省略】


NETWORK:
/h/STRMobileViewAPI.do
 キャッシュマニフェストファイルの1行目は、常に「CACHE MANIFEST」です。
□ 「#」はコメント
 「#」から始まる行はコメントです。キャッシュの更新はマニフェストファイルが変更されたことで検出されます。キャッシュの更新をWebブラウザに通知するためにバージョン番号や日付を入れておきます。
□ iPhoneのSafariは更新のチェックのリクエスト自体が来ない
 ここで注意ですが、一般にキャッシュマニフェストファイルの説明では、「1byteでも変更があると、キャッシュが更新される」とありますが、iPhoneのSafariの場合、更新のチェックのリクエスト自体が来ないので、いくらコメント部分を変更しても、それだけではキャッシュは更新されません。
 後述しますが、JavaScriptで明示的にキャッシュを更新する必要があります。
□ 「CACHE:」はキャッシュしたいURL
 「CACHE:」の行以降にキャッシュしたいURLを列挙します。ワイルドカードは使えないので、キャッシュしたいJavaScript、画像、CSSを1行に1つずつ記述します。
□ 「NETWORK:」はキャッシュしたくないURL
 「NETWORK:」の行の後にはキャッシュしたくないURLを列挙します。Ajaxで取得するXMLやJSONを返すURLは、こちらに記述します。
HTMLでキャッシュマニフェストを有効にするには
 HTMLでアプリケーションキャッシュを有効にするには、以下のように<html>タグの中で「manifest」属性を使って、このキャッシュマニフェストファイルを指定します。
<!doctype html>
<html manifest="cache.manifest">
<head>


【省略】


</head>
<body>


【省略】


</body>
</html>

Webサーバをキャッシュマニフェストに対応するには
 キャッシュマニフェストファイルは、「text/cache-manifest」というMIMEタイプで送信する必要があります。
□ Apacheの場合
 Webサーバとして「Apache httpd」を使っている場合、デフォルトではキャッシュマニフェストに対応していないので、「httpd.conf」ファイルに以下の行を追加して「 .manifest」という拡張子のファイルのときに、このMIMEタイプで送信するように設定します。
AddType text/cache-manifest .manifest
□ Tomcatの場合
 「Tomcat」などのJava用のアプリケーションコンテナの場合は、アプリごとの「web.xml」の<welcome-file-list>要素の直前に、以下の<mime-mapping>要素を追加します。
<mime-mapping>
<extension>manifest</extension>
<mime-type>text/cache-manifest</mime-type>
</mime-mapping>

 これで、アプリケーションキャッシュに指定したコンテンツがキャッシュされるようになります。

HTMLファイルをキャッシュマニフェストに含めるには
 キャッシュマニフェストファイルに、すべてのJavaScriptファイル、画像ファイル、CSSファイルを記述すると、ページのロード時間を劇的に短縮できます。
 キャッシュマニフェストには、これらのファイルだけでなくHTML自体を含めることができます。HTML自体をキャッシュに格納すると、そのURLのときは一切サーバにリクエストを出さずに画面を表示可能になります。
 先ほどの例では「CACHE:」の1行目の「/h/MobileView.do」がHTMLです。
 すべてのデータをAjaxで取得するアプリは、HTMLは毎回同じファイルになるはずなので、このようにHTML自体をキャッシュできます。
 こうしておくと、電波がまったく届いていないオフライン状態でも、Safariのブックマークなどから起動すると、普通にアプリが動作します。

対応必須! キャッシュの更新スクリプト
 このようにiPhoneのSafariでは、キャッシュマニフェストによるアプリケーションキャッシュは、かなり強力ですが、設定画面から[キャッシュを消去]を選択しても、キャッシュは消去されません。
 前述したとおり、キャッシュマニフェストファイルを変更してもマニフェストファイル自体がキャッシュされてしまいリクエストが来ないので、キャッシュを更新できないのです。
□ キャッシュデータの削除はiTunesで"復元"のみ?
 いろいろ試してみましたが、一度キャッシュされてしまったデータを削除するには、iTunesからiPhoneを"復元"するほかなさそうです。
 さすがにこれでは、アプリの不具合修正やバージョンアップがあっても更新できず実用的ではないので、アプリケーションキャッシュを使う場合は、JavaScriptで更新をチェックする処理をセットで作っておき、スクリプトから明示的にキャッシュを更新する必要があります。
 これをやらずに、いきなりアプリケーションキャッシュを試すと、もうそのURLでは二度とロードしなくなるので、要注意です。
□ キャッシュのチェックスクリプト
 JavaScriptでキャッシュを更新するのは簡単です。スクリプトの中で「window.applicationCache.update()」を呼び出せばOKです。この関数を呼び出すと、キャッシュマニフェストファイルをサーバからダウンロードしてキャッシュが更新されていないかどうかをチェックします。
 ここで初めて、マニフェストファイルに入れておいたコメントの中のバージョン番号が役に立ちます。もし、キャッシュが更新されていた場合は、applicationCacheオブジェクトでupdatereadyイベントが発生するので、「applicationCache.swapCache()」を呼び出して新しいキャッシュに切り替えます。
 これを実行するスクリプトは、以下のようになります。
var cache = window.applicationCache;
cache.addEventListener("updateready", function() {
if (confirm('アプリケーションの新しいバージョンが利用可能です。更新しますか?')) {
cache.swapCache();
location.reload();
}
});
if (navigator.onLine) {
cache.update();
}
 このスクリプトをHTMLのロードイベントで動作する関数の中に記述すると、ページのロード時にキャッシュの更新をチェックして、更新する必要がある場合は確認画面を表示してキャッシュを更新するようになります。

0 件のコメント:

コメントを投稿