HTML5のApplicaiton Cacheについて使ってみたまとめ

「オフラインでもWebアプリって使えないの？」というお話があり、
HTML5のApplication Cacheが咄嗟に思いつきはしたものの、触ったこともなかったので、
調べながらちょっと試してみた。

# はじめに
## Offline Web Application仕様
W3C： http://www.w3.org/TR/html5/browsers.html#offline

## セキュリティ問題
ちょっと調べれば出てくる話ですが、主にキャッシュポイズニングの問題について挙げられています。
その議論については、この中ではあげませんので、他所を参照してください。

# 簡単なサンプルで動作確認する
## HTMLファイル
```html:sample.html
<!DOCTYPE html>
<html manifest="manifest.appcache">
<body>
<script type="text/javascript">
var appCache = window.applicationCache;

appCache.update();

if(appCache.status == window.applicationCache.UPDATEREADY) {
  appCache.swapCache();
}
</script>
Hello, World!
</body>
</html>
```
下記の機能だけのシンプルなサンプルです。

* 画面には「Hello, World!」が表示されるだけ
* javascriptはApplication Cache対象データが更新されていた場合に再取込する仕掛け

## マニフェストファイル
```manifest.appcache
CACHE MANIFEST
# Ver.20150723_01

sample.html
```
意味的には「sample.htmlをキャッシュして使ってね」ぐらいです。
（ちゃんとした設定の話は後述します。）

## Webサーバの設定ファイル
当方のWebサーバはApache。マニフェストファイルのContent-typeが正しく流れるように、.htaccessを同ディレクトリに配置してWebサーバの設定は簡便化しました。

```apache:.htaccess
AddType text/cache-manifest .appcache
```

# 動きの確認
下記のステップでやっていきます。

* Step1: オンラインでsample.htmlを見る
* Step2: オフラインでsample.htmlを見る（Application Cacheの動作確認）
* Step3: sample.htmlをちょっと変えて、オンラインでsample.htmlを見る（Cacheデータ利用況確認）
* Step4: マニフェストファイルを変更して、オンラインでsample.htmlを見る（Cacheデータ更新確認）

なお、sample.htmlの参照にはFireFox 38を使いました。

## Step 1: オンラインでsample.htmlを見る
当然見れました。画面に「Hello, World」の文字。
ウインドウ見ても、Cacheが取り込まれたというのはわからないカンジ。

## Step 2: オフラインでsample.htmlを見る（Application Cacheの動作確認）
Step 1の結果と同様の結果を得ました。Application Cacheは想定どおり動いているようです。
ウインドウ見ても、これがキャッシュだとは見てもわからないカンジ。

## Step 3: sample.htmlをちょっと変えて、オンラインでsample.htmlを見る（Cacheデータ利用状況確認）
sample.htmlを下記のように変更しました。

```html:sample.html
<!DOCTYPE html>
<html manifest="manifest.appcache">
<body>
<script type="text/javascript">
var appCache = window.applicationCache;

appCache.update();

if(appCache.status == window.applicationCache.UPDATEREADY) {
  appCache.swapCache();
}
</script>
Hello, Sekai!
</body>
</html>
```

「Hello, World!」が「Hello, Sekai!」になっていれば、sample.htmlがリロードされたことになります。

この状態でブラウザからアクセスしても、**表示は「Hello, World!」のままでした。**
**ブラウザ内のキャッシュは更新されないようです。**

## Step 4: マニフェストファイルを変更して、オンラインでsample.htmlを見る（Cacheデータ更新確認）
マニフェストファイルを下記のとおり変更しました。

```manifest.appcache
CACHE MANIFEST
# Ver.20150723_02

sample.html
```

バージョン表記を変えただけで意味は同じです。

この状態でブラウザからアクセスすると、**表示は「Hello, Sekai!」に変更になりました。**
**マニフェストファイルを更新することで変更があったとみなされます。**
事前にWebで調べていて、バージョン情報のような記載を変えるTipsを見ていたので、
この方法をやってみました。

以上で、一通りApplication Cacheの動作を見てみました。

# マニフェストファイルの書き方
前述ではもっともシンプルな例を挙げましたが、
下記のキーワードにより記載することで、より管理が可能です。
（というか、ここまでしないとあまり意味ないかも。）

改めて、別のサンプルを用意します。下記にあわせて説明していきます。

```manifest.appcache
CACHE MANIFEST
# Ver.20150723_02

CACHE:
sample.html

NETWORK:
alwaysnetwork.html

FALLBACK:
*.html fallback.html

SETTINGS:
prefer-online

```

## CACHE MANIFEST（1行目）
このリソースがマニフェストファイルであることを示します。
必ず1行目に「CACHE MANIFEST」と書く必要があり、省略不可です。

## コメント行（2行目）
行頭が「#」になっている行はコメントとして扱われます。
例ではバージョン情報を記載していますが、内容は自由です。

前述のとおり、マニフェストファイルが更新されなければキャッシュ更新も行われないため、
Tipsとしてバージョン情報を記載して、対象リソースの変更がなくても
バージョン情報を変更することで、ブラウザ側にキャッシュ更新を促す方法は
結構使えるのではないでしょうか。

## explictセクション(4～6行目)
このセクションでは、ブラウザ側にキャッシュとして保持してほしいリソースを指定します。

4行目「CACHE:」はexplicitセクションの始まりであることを宣言しており、
この次の行から指定されるリソースがキャッシュとして保持される対象となります。

なお、「CACHE:」は省略可能で、省略した場合はCACHE MANIFESTの下から次のセクションまでに
記載されたリソースをキャッシュ対象として認識し、保持します。

なお、キャッシュ対象リソースがない状態は指定できません。

## online whitelist セクション(7～9行目)
このセクションでは、必ずネットワーク経由で取得したいリソースを指定します。

7行目「NETWORK:」はonline whitelistセクションの始まりであることを宣言しており、
この次の行から指定されるリソースはキャッシュされず、常にネットワーク上から取得される対象となります。

このセクションで指定するリソースにはワイルドカード「*」をしようすることができます。

指定するものがない場合はこのセクションを作成する必要はありません。

## fallback セクション(10～12行目）
このセクションでは、オフライン時に代替するリソースを指定します。

10行目「FALLBACK:」はfallbackセクションの始まりであることを宣言しており、
この次の行から指定されるものが代替リソースとなります。

11行目の「*.html error.html」は、
オフライン時に「.html」で終わるリソースに対してアクセスされた場合、
「error.html」を見せるように指定しています。

このように指定した場合、**同一オリジンの範囲で、実際に存在しないURLを指定した場合でも、**
**「.html」で終わるものに対してリクエストした場合、「error.html」が表示されます。**

このセクションで指定するアクセス対象のリソースにはワイルドカード「*」をしようすることができますが、
代替されるリソースを指定する場合には使用できません。
また、代替されるリソースは、キャッシュとして保持される対象となります。

## settings セクション(13行目以降）
このセクションでは、設定項目を指定します。

13行目「SETTINGS:」はsettingsセクションの始まりであることを宣言しており、
その次の行から設定を指定しますが、現在指定できるのは「prefer-online」のみです。

「prefer-online」を指定した場合、デフォルトの「cache mode」から「prefer-online」に切り替わり、
キャッシュはオフライン時のみ利用され、オンライン時はネットワークからリソースを取得するようになります。

# 使ってみてわかったこと
## どのセクションでも指定されないリソースはどうなるのか
実際マニフェストを作る場合、すべてのリソースをexplicitセクション(CACHE)またはonline whitelistセクション(NETWORK)に記載していくことは状況によっては難しいこともあるんじゃないかと考え、
どこにも書かなかった場合はどういう振る舞いになるのか、ちょっと見てみました。

**結論からいうと、NETWORKに記載したものと同様の動きに見えます。**
そもそも、キャッシュの対象として挙がっていないものはキャッシュの対象になりえないので、動きとしては至って自然です。

これでいくと、online whitelistセクションでは、
ネットワーク上から最新を取得してほしいものを明示する目的に使用するほか、
ワイルドカード(*)を使えることを考慮して、
URLのパスレベルでオンライン取得対象を指定するような使い方のほうがいいのかもしれません。

## キャッシュされているかどうかを確認する
ブラウザによって異なるようです。
当方はFirefoxを使用していますが、URL指定箇所に「about:cache」と指定すると内容が確認できました。