我目前正在使用Cache Manifest(如here所述)。这有效地使得在用户离线时运行应用程序所需的资源。
不幸的是,它运作得有点好。
加载缓存清单后,Firefox 3.5+会缓存缓存清单中显式引用的所有资源。但是,如果服务器上的文件已更新,并且用户尝试在线时强制刷新页面(包括缓存清单本身),Firefox将绝对拒绝提取任何内容。应用程序在缓存的最后一点保持完全冻结。问题:
答案 0 :(得分:25)
我想我已经弄明白了:如果一个缓存清单中出现错误(比如,引用的文件不存在),那么Firefox将完全停止处理与applicationCache相关的任何内容。这意味着,它不会更新缓存中的任何内容,包括缓存的缓存清单。
为了发现这是问题,我borrowed some code from 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提供一个功能,它至少会将格式错误的缓存清单打印到错误控制台。它不应要求自定义代码附加到这些事件,以将问题诊断为重命名文件。
答案 1 :(得分:15)
我使用了来自HTML5 Rocks: Update the cache的代码:
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);
答案 2 :(得分:7)
免责声明:我对清单和缓存的体验是Safari和FF可能会以不同的方式处理某些事情。
你是对的。如果清单上列出的任何文件无法找到,则不会发生缓存。
即使您在线,浏览器也只会检查清单文件。在等待清单文件时,它将继续从缓存加载网站 - 这样不会延迟渲染 - 但这意味着您在第一次加载时看不到任何更改。
下次加载网站时,如果上次加载时清单发生更改,则会加载新文件。
总是需要重新开始两次才能看到任何变化。事实上,我有时不得不重新加载3次以查看更新。不知道为什么。
调试时,我使用php动态生成我的清单文件,因此文件名中不会出现拼写错误。我还每次都会随机生成版本号以强制更新,但仍然有一个离线webapp用于测试。
完成后,php文件只能使用常量版本号回显保存的清单数据,并始终使用缓存。
我最近在玩清单和缓存时学到的一些东西。它效果很好,但可能令人困惑。
没有到期日。要取消缓存,您必须更改清单文件以使其中没有任何内容并执行重新加载。在Safari上,清除用户缓存会清除所有缓存的文件。
答案 3 :(得分:7)
我遇到了同样的问题:一旦Firefox保存了脱机文件,它就不会重新加载它们。 Chrome按预期工作,它检查清单文件中的更改,并在清单文件更改时重新加载所有内容。 Firefox甚至没有从服务器下载清单文件,因此无法注意到更改。
经过调查,我发现Firefox正在缓存缓存清单文件(旧式缓存,而不是脱机缓存)。将清单文件的缓存标头设置为Cache-Control: no-cache, private
解决了这个问题。
答案 4 :(得分:3)
我制作了一个Firefox附加组件,它使Cache Manifest无效并清除HTML5本地存储。
http://sites.google.com/site/keigoattic/home/webrelated#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()
答案 5 :(得分:2)
嗯,我刚刚在清单上调用了update(),对清单文件进行了编辑更改,并收到了完整的检查/下载/准备序列,重新加载了一次,并且我在一个文件中进行了一次文本更改我的js文件显示在我的应用程序的初始页面中,很快就出现了。
似乎我只需要一次重装。