如何正确使在线/离线Web应用程序的HTML5缓存清单无效?

时间:2009-11-11 14:37:48

标签: html firefox caching html5 offline-caching

我目前正在使用Cache Manifest(如here所述)。这有效地使得在用户离线时运行应用程序所需的资源。

不幸的是,它运作得有点好。

加载缓存清单后,Firefox 3.5+会缓存缓存清单中显式引用的所有资源。但是,如果服务器上的文件已更新,并且用户尝试在线时强制刷新页面(包括缓存清单本身),Firefox将绝对拒绝提取任何内容。应用程序在缓存的最后一点保持完全冻结。问题:

  1. 我希望Firefox在网络连接失败时有效地仅依赖缓存的资源。我尝试过使用FALLBACK块,但无济于事。这甚至可能吗?
  2. 如果#1不可能,用户是否可以强制刷新页面并绕过此缓存(ctrl-F5不执行此操作,也无法清除浏览器的缓存,令人震惊)无法清除其私有数据?或者,缓存清单机制是否支持到期标头,并且它的行为是否记录在任何地方?

6 个答案:

答案 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可能会以不同的方式处理某些事情。

  1. 你是对的。如果清单上列出的任何文件无法找到,则不会发生缓存。

  2. 即使您在线,浏览器也只会检查清单文件。在等待清单文件时,它将继续从缓存加载网站 - 这样不会延迟渲染 - 但这意味着您在第一次加载时看不到任何更改。

  3. 下次加载网站时,如果上次加载时清单发生更改,则会加载新文件。

  4. 总是需要重新开始两次才能看到任何变化。事实上,我有时不得不重新加载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文件显示在我的应用程序的初始页面中,很快就出现了。

似乎我只需要一次重装。