-
Notifications
You must be signed in to change notification settings - Fork 5
Wing
Wing は、サーバ上のアセットファイルをブラウザ上にキャッシュし、アセットの変更に自動追従する機能を持ったクライアントサイドキャッシュライブラリです。
Wing は Tombo の一部ですが、単体でも利用可能です。
以下の特徴があります。
- 通信の回数と量を減らし、ユーザの待ち時間を最小化します
- ファイル毎に更新確認のための通信を行いません。更新チェックはマニフェストファイルで一括して行います
- ファイル毎の更新確認が不要になり、その時間を使ってcssやjsなどのページの表示に必要なファイルを処理できます。結果的にページが素早く表示されるようになります
- アセットをマニフェストで管理します(台帳で管理します)
- マニフェストは、アセットとキャッシュに関する情報(ディレクトリ、ID, パス, エンコード方法等)をまとめたJSONデータです
- Wing は初期化時にマニフェストをサーバから取得し、自動的に追従します
- キャッシュ可能なデータ量は 3.6〜5.0MB です
- バイナリデータが多いほどキャッシュ容量は目減りします
- バイナリデータはテキストデータの1.33倍の容量が必要になります
- ファイル単体で2MBを超す大きなファイルはキャッシュできません(例: WebFontファイル)
- iOS では一部のデータ(mp3やaac)はキャッシュできません
- Wing で保存できないデータや、アセットが巨大な場合は、ApplicationCache の利用を検討してください
Wing によるクライアントサイドキャッシュと、従来の方法を比較です。
手段/方法 | キャッシュの 永続性 |
キャッシュの 部分更新 |
通信の抑止 | 導入のしやすさ | キャッシュ容量 |
---|---|---|---|---|---|
ブラウザキャッシュ | × | ◎ | × | ◎ | 不明 (端末や実装に依存) |
ApplicationCache | ◎ | △ | × | △ | 2.5MB (公称 5MB) |
ETag ヘッダ | ◯ | ◯ | × | × | 不明 |
Expires ヘッダ | ◎ | × | ◎ | △ | 不明 |
CDN | ◎ | ◎ | × | ◯ | --- |
Wing | ◎ | ◎ | ◎ | ◯ | 3.6 〜 5MB |
Zabuton | ◎ | ◎ | ◎ | △ | 800MB以上可能 (上限は端末に依存) |
- ブラウザキャッシュ
- MobileSafari のブラウザキャッシュはデバイスの再起動で消えてしまいますが、Wingのキャッシュは消えません
- ブラウザキャッシュは、キャッシュが溢れると順番に消えてしまいますが、Wingのキャッシュは消えません
- ApplicationCache
- ApplicationCache は一部だけ更新できず、一旦全てのファイルを更新しようと通信が発生しますが(その結果は200または304になります)、Wing は更新が必要なファイルしか取得しません
- ApplicationCacheは、HTML自体をキャッシュしてしまうためページ遷移型のアプリでは利用できませんが、Wingはページ遷移型のアプリにも導入可能です
- ETag ヘッダ
- ETag はキャッシュが存在する場合にデータの転送量がゼロになりますが、通信自体は発生してしまいます、Wing は通信自体を行いません
- ETag は負荷分散構成のサーバでは使えません
- Expires ヘッダ
- Expires はキャッシュ期間中にブラウザからサーバへの更新確認のための通信を抑止できますが、サーバ上でファイルを更新してもクライアント側は更新されません(ファイル名を変更する必要があります)。Wing を使うと通信を抑止するだけではなく柔軟な運用が可能になります
- Expires は、ずっと変化しない事が前提の静的なアセットをキャッシュするための機能ですが、Wingは頻繁に更新されるアセットのキャッシュにも利用できます
- CDN
- CDN を使うとサーバにリクエストするたびに料金が発生しますが、Wing はキャッシュ後に通信を行いません
Wing は Zabuton の機能縮小版(サブセット)です。Wing に以下の機能は実装されていません。
- iframe を使った無限ストレージ機能
- postMessage を使ったドメイン間通信の機能
- メモリ上のキャッシュを一定時間でGCする機能
- デバッグ用に実際にはキャッシュしないブラックホールストレージを選択する機能
- UTF16で格納されるデータを特殊な方法でエンコードし、通常の2倍のデータを保存する機能(doubler)
- Scene とテンプレート機能
- マニフェストファイルの互換性
- Zabuton用のマニフェストはWingで読み込めません、互換性がありません
-
var wing = new Wing(options);
でインスタンスを生成し -
wing.init(callback)
で初期化とマニフェストの更新を行います -
wing.fetchAll(callback)
でキャッシュを更新し -
wing.get(id, toDataURI)
でキャッシュ済みのアセットを取り出します
// JSX
import "Wing.jsx";
class _Main {
static function main(args: string[]):void {
var options = {
verbose: false, // デバッグ用の log を出力する/しない
cache_busting: false, // XHRのブラウザキャッシュをOFFにする/しない
manifest: null, // マニフェストオブジェクト or マニフェストファイルURL
hook_url: function(url:string):string { // アセットのURLを置換するフック関数の指定
//return "http://example.com/" + url;
return url;
}
}:Map.<variant>;
var wing = new Wing(options);
wing.init(function(err:Error) { // 初期化完了でコールバック
wing.fetchAll(function(err:Error, id:Array.<string>):void { // キャッシュの追従完了でコールバック
log "Wing.fetchAll: " + id.join(", ");
});
});
}
}
wing.fetchAll()
により、全てのキャッシュがオンメモリになります(最大10MBのメモリを使用します)。
wing.fetchAll()
の中で、wing.get(id)
を行うとキャッシュデータを取り出せます。
// JSX
wing.fetchAll(function(err:Error, id:Array.<string>):void {
log wing.get("hoge.txt"); // DataURIヘッダなしでキャッシュを取りだす "hello world"
log wing.get("piyo.png", true); // DataURIヘッダ付きでキャッシュを取り出す "data:image/png;base64,..."
});
Wing#is(id:string):boolean
は アセット(id)がマニフェストに存在する場合に true を返します。
false ならそのようなアセットidは存在しません。
Wing#has(id:string):boolean
は アセット(id)が fetch 済み(データがメモリ上に載っている状態)なら true を返します。
false ならfetch する必要があります。
Wing#fetch(id:string, fetchedCallback:function(err:Error, id:string):void):void
はアセット(id)をサーバから取得しクライアントストレージにキャッシュします。
アセットに対して以下の処理を行います。
- 内容が古くなっている → 現在のキャッシュを捨て、サーバから再取得を行いキャッシュする
- 追加されたアセット → サーバから取得を行いキャッシュする
- 不要なアセット → 不要なキャッシュを捨てる
Wing#fetchAll(fetchedCallback:function(err:Error, id:Array.<string>):void):void
は全てのアセットをサーバから取得しクライアントストレージにキャッシュします。
以下の処理を全てのアセットに対して行います。
- 内容が古くなっている → 現在のキャッシュを捨て、サーバから再取得を行いキャッシュする
- 追加されたアセット → サーバから取得を行いキャッシュする
- 不要なアセット → 不要なキャッシュを捨てる
Wing#get(id:string, toDataURI:boolean = false):string
は fetch 済みのアセット(id)を文字列として取り出します。
アセットがバイナリデータで、第2引数が true なら、文字列の先頭に data:MimeType;base64;
を追加します。
Wing#clear(callback:function(err:Error):void = null):void
は、キャッシュをクリアします。
キャッシュクリアは、以下の2通りの方法でもできます
- ブラウザのUIから「データを削除(MobileSafari)」や「キャッシュの消去(chrome)」を選択します
-
delete localStorage.__WING__
を行いDELETE FROM Wing
SQLを実行します
意図的にキャッシュを再同期させるには、wing のインスタンを一度破棄し、再度生成してください。
// JSX
wing = null;
wing = new Wing(options);
Wing で使用するマニフェストファイルのフォーマットです。
{
"dirs": {
"img1": "assets/images/1/",
"img2": "assets/images/2/",
"txt1": "assets/text/"
},
"assets": {
"16_00":["121213", 1, 2, 807, "png", "img1", "16_00.png"],
"16_01":["121213", 1, 2, 843, "png", "img1", "16_01.png"],
"16_30":["121213", 2, 2, 843, "png", "img2", "16_30.png"],
"a.txt":["124445", 2, 1, 5, "text", "txt1", "a.txt"]
}
}
-
dirs
はアセットを格納するディレクトリの指定です。{ keyword: directory, ... }
で複数指定可能です-
directory
は末尾が/
で終わるように指定してください
-
-
assets
はアセットのリストです。アセットの情報を[hash, db, code, size, ext, dir, file]
の配列で指定します-
hash
- MD5で生成した16進数文字列の先頭6文字です。手動で作成する場合は適当な6文字の数字を設定してください -
db
- キャッシュをどのDBに保存するかの指定です。1を指定すると LocalStorage に保存し、2を指定するとWebSQLに保存します。 0 を指定するとストレージに保存しません -
code
- キャッシュをストレージに保存する際のエンコードの指定です。 1 はそのまま保存します, 2 はBase64化した状態で保存します -
size
- アセットのファイルサイズです -
ext
- "js" や "css" などの拡張子です -
dir
- ディレクトリの指定です。dirs
に存在する名前を指定します -
file
- ファイル名の指定です。dirs[dir] + file
が実際のURLになります
-
まずは、dirs
を含んだマニフェストファイル(asset.manifest.json)をエディタで作成します。
この例では o/assets/asset.manifest.json を作成しています。
{
"dirs": {
"img1": "o/assets/images/1/",
"img2": "o/assets/images/2/",
"txt": "o/assets/text/"
},
}
次に、node toast.js -v o/assets/asset.manifest.json
を実行します。
node toast.js
コマンドは dirs
に指定したディレクトリ直下のファイルを検索し、見つかったファイルを assets
にリストアップします。
{
"dirs": {
"img1": "o/assets/images/1/",
"img2": "o/assets/images/2/",
"txt": "o/assets/text/"
},
"assets": {
"16_00.png": [ "c10c96", 1, 2, 807, "png", "img1", "16_00.png" ],
"16_01.png": [ "782602", 1, 2, 843, "png", "img1", "16_01.png" ],
"16_02.png": [ "5a1f07", 1, 2, 841, "png", "img1", "16_02.png" ],
"16_03.png": [ "b024dc", 1, 2, 834, "png", "img1", "16_03.png" ],
"16_04.png": [ "b1c6c9", 1, 2, 849, "png", "img1", "16_04.png" ],
"16_10.png": [ "f7f8c7", 1, 2, 764, "png", "img1", "16_10.png" ],
"16_11.png": [ "201a89", 1, 2, 765, "png", "img1", "16_11.png" ],
"16_12.png": [ "402cb5", 1, 2, 754, "png", "img1", "16_12.png" ],
"16_13.png": [ "db226c", 1, 2, 767, "png", "img1", "16_13.png" ],
"16_14.png": [ "0efc53", 1, 2, 725, "png", "img1", "16_14.png" ],
"16_20.png": [ "0e57c2", 1, 2, 682, "png", "img1", "16_20.png" ],
"16_21.png": [ "1c5959", 1, 2, 679, "png", "img1", "16_21.png" ],
"16_22.png": [ "383b77", 1, 2, 684, "png", "img1", "16_22.png" ],
"16_23.png": [ "b2ee66", 1, 2, 708, "png", "img1", "16_23.png" ],
"16_24.png": [ "8d6c6b", 1, 2, 602, "png", "img1", "16_24.png" ],
"16_30.png": [ "b62bec", 1, 2, 756, "png", "img2", "16_30.png" ],
"16_31.png": [ "437b1a", 1, 2, 762, "png", "img2", "16_31.png" ],
"16_32.png": [ "5da4b2", 1, 2, 761, "png", "img2", "16_32.png" ],
"16_33.png": [ "b5a7b0", 1, 2, 760, "png", "img2", "16_33.png" ],
"16_34.png": [ "2a1580", 1, 2, 724, "png", "img2", "16_34.png" ],
"16_40.png": [ "978dd3", 1, 2, 748, "png", "img2", "16_40.png" ],
"16_41.png": [ "0d2185", 1, 2, 758, "png", "img2", "16_41.png" ],
"16_42.png": [ "b24dd8", 1, 2, 760, "png", "img2", "16_42.png" ],
"16_43.png": [ "f6ccd6", 1, 2, 752, "png", "img2", "16_43.png" ],
"16_44.png": [ "183d99", 1, 2, 725, "png", "img2", "16_44.png" ],
"16_50.png": [ "8ff6b0", 1, 2, 592, "png", "img2", "16_50.png" ],
"16_51.png": [ "690bdd", 1, 2, 610, "png", "img2", "16_51.png" ],
"16_52.png": [ "197751", 1, 2, 601, "png", "img2", "16_52.png" ],
"16_53.png": [ "76b19f", 1, 2, 620, "png", "img2", "16_53.png" ],
"16_54.png": [ "c23995", 1, 2, 577, "png", "img2", "16_54.png" ],
"a.txt": [ "dc9f32", 1, 1, 7, "txt", "txt", "a.txt" ]
}
}
注意: node toast.js -v o/assets/asset.manifest.json
コマンドは実行するたびに、assets: { ... }
を再作成します。
toast.js は マニフェストファイルの assets
部分の更新を行うツールです。
node toast.js -v ./assets/asset.manifest.json
のように使用します。
詳しくは node toast.js --help
を見てください。