オンライン/オフライン Web アプリの HTML5 キャッシュ マニフェストを適切に無効にする方法は?
-
19-09-2019 - |
質問
現在、キャッシュマニフェストを使用しています(説明どおり) ここ)。これにより、ユーザーがオフラインのときにアプリケーションの実行に必要なリソースを効果的に利用できるようになります。
残念ながら、それは少しうまく機能しすぎます。
キャッシュ マニフェストがロードされた後、Firefox 3.5 以降は、キャッシュ マニフェストで明示的に参照されているすべてのリソースをキャッシュします。ただし、サーバー上のファイルが更新され、ユーザーがオンライン中にページ (キャッシュマニフェスト自体を含む) を強制更新しようとすると、Firefox は何もフェッチすることを絶対に拒否します。アプリケーションは、最後にキャッシュされた時点で完全にフリーズしたままになります。質問:
- ネットワーク接続が失敗した場合に、Firefox が事実上、キャッシュされたリソースのみに依存するようにしたいと考えています。FALLBACK ブロックを使用してみましたが、役に立ちませんでした。これも可能でしょうか?
- #1 が不可能な場合、ユーザーは個人データをクリアする以外に、ページを強制的に更新してこのキャッシュをバイパスすることは可能でしょうか (驚くべきことに Ctrl-F5 を押しても実行できませんし、ブラウザのキャッシュをクリアしても実行できません)。あるいは、キャッシュマニフェストメカニズムは有効期限ヘッダーをサポートしていますか、またこれに関するその動作はどこかに文書化されていますか?
解決
これは理解できたと思います:キャッシュマニフェストにエラーがある場合 (参照ファイルが存在しないなど)、Firefox は applicationCache 関連の処理を完全に停止します。つまり、キャッシュされたキャッシュマニフェストを含め、キャッシュ内の何も更新されません。
これが問題であることを明らかにするために、私は Mozilla からコードを借用 これをアプリケーションの新しい (キャッシュされていない) HTML ファイルにドロップしました。ログに記録された最後のメッセージには、キャッシュマニフェストに問題がある可能性があることが記載されており、確かに(ファイルが欠落しています)問題がありました。
// Convenience array of status values
var cacheStatusValues = [];
cacheStatusValues[0] = 'uncached';
cacheStatusValues[1] = 'idle';
cacheStatusValues[2] = 'checking';
cacheStatusValues[3] = 'downloading';
cacheStatusValues[4] = 'updateready';
cacheStatusValues[5] = 'obsolete';
// Listeners for all possible events
var cache = window.applicationCache;
cache.addEventListener('cached', logEvent, false);
cache.addEventListener('checking', logEvent, false);
cache.addEventListener('downloading', logEvent, false);
cache.addEventListener('error', logEvent, false);
cache.addEventListener('noupdate', logEvent, false);
cache.addEventListener('obsolete', logEvent, false);
cache.addEventListener('progress', logEvent, false);
cache.addEventListener('updateready', logEvent, false);
// Log every event to the console
function logEvent(e) {
var online, status, type, message;
online = (isOnline()) ? 'yes' : 'no';
status = cacheStatusValues[cache.status];
type = e.type;
message = 'online: ' + online;
message+= ', event: ' + type;
message+= ', status: ' + status;
if (type == 'error' && navigator.onLine) {
message+= ' There was an unknown error, check your Cache Manifest.';
}
log('
'+message);
}
function log(s) {
alert(s);
}
function isOnline() {
return navigator.onLine;
}
if (!$('html').attr('manifest')) {
log('No Cache Manifest listed on the tag.')
}
// Swap in newly download files when update is ready
cache.addEventListener('updateready', function(e){
// Don't perform "swap" if this is the first cache
if (cacheStatusValues[cache.status] != 'idle') {
cache.swapCache();
log('Swapped/updated the Cache Manifest.');
}
}
, false);
// These two functions check for updates to the manifest file
function checkForUpdates(){
cache.update();
}
function autoCheckForUpdates(){
setInterval(function(){cache.update()}, 10000);
}
return {
isOnline: isOnline,
checkForUpdates: checkForUpdates,
autoCheckForUpdates: autoCheckForUpdates
}
これは確かに役に立ちましたが、少なくともエラー コンソールに不正なキャッシュ マニフェストを出力する機能を Mozilla に必ずリクエストする必要があります。ファイルの名前が変更されたというような些細な問題を診断するために、これらのイベントにカスタム コードを添付する必要はありません。
他のヒント
からのコードを使用しました HTML5 ロック:キャッシュを更新する:
window.addEventListener('load', function(e) {
if (window.applicationCache) {
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
// Swap it in and reload the page to get the new hotness.
window.applicationCache.swapCache();
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
} else {
// Manifest didn't changed. Nothing new to server.
}
}, false);
}
}, false);
免責事項:マニフェストとキャッシュに関する私の経験では、すべて Safari と FF ではいくつかの処理が異なる場合があります。
たしかにそれは正しいね。マニフェストにリストされているファイルが見つからない場合、キャッシュは行われません。
オンラインであっても、ブラウザはマニフェスト ファイルのみをチェックします。マニフェスト ファイルを待機している間、キャッシュからサイトの読み込みが続行されます。これにより、レンダリングが遅れることはありませんが、最初の読み込みでは変更が表示されないことになります。
次回サイトをロードするときに、前回のロードでマニフェストが変更されていた場合は、新しいファイルがロードされます。
変更を確認するには、常に 2 回リロードする必要があります。実際、更新を確認するために 3 回リロードしなければならないこともありました。理由はわかりません。
デバッグ時には、php を使用してその場でマニフェスト ファイルを生成するため、ファイル名のタイプミスが発生する可能性はありません。また、更新を強制するために毎回バージョン番号をランダムに生成しますが、テスト用のオフライン Web アプリはまだ残っています。
完了すると、PHP ファイルは保存されたマニフェスト データを一定のバージョン番号でエコーするだけで、キャッシュは常に使用されます。
最近マニフェストとキャッシュを使って遊んでいて学んだことがいくつかあります。うまく機能しますが、混乱する可能性があります。
有効期限はありません。キャッシュを解除するには、マニフェスト ファイルに何も含まれないように変更し、リロードする必要があります。Safari では、ユーザー キャッシュをクリアすると、キャッシュされたファイルがすべてクリアされます。
私も同じ問題を抱えていました:Firefox がオフライン ファイルを保存すると、それらを再ロードすることはありません。Chrome は期待どおりに動作し、マニフェスト ファイルの変更をチェックし、マニフェスト ファイルが変更された場合はすべてをリロードしました。Firefox はサーバーからマニフェスト ファイルをダウンロードすることさえしなかったため、変更に気づくことができませんでした。
調査の結果、Firefox がキャッシュ マニフェスト ファイル (オフライン キャッシュではなく、昔ながらのキャッシュ) をキャッシュしていることがわかりました。マニフェスト ファイルのキャッシュ ヘッダーを次のように設定します。 Cache-Control: no-cache, private
問題を解決しました。
キャッシュマニフェストを無効にし、HTML5 ローカルストレージをクリアする Firefox アドオンを作成しました。
http://sites.google.com/site/keigoattic/home/webpopular#TOC-Firefox-HTML5-Offline-Cache-and-Loc
エラー コンソールに次のコードを入力して、キャッシュ マニフェストを無効にすることもできます。
// invalidates the cache manifest
var mani = "http://.../mysite.manifest"; // manifest URL
Components.classes["@mozilla.org/network/application-cache-service;1"].getService(Components.interfaces.nsIApplicationCacheService).getActiveCache(mani).discard();
または、アドレス バーに以下のコードを入力すると、キャッシュが手動で更新されます。
javascript:applicationCache.update()
うーん、マニフェストファイルに編集変更を加えた後、キャッシュ上で update() を呼び出したところ、チェック/ダウンロード/準備完了の完全なシーケンスを受け取り、1 回のリロードと、JS の 1 つで行ったテキストの変更が行われました。アプリの最初のページに表示されるファイルがすぐに表示されました。
リロードは1回だけ必要なようです。