55

我目前正在使用缓存清单(如此所述)。这有效地使用户离线时运行应用程序所需的资源可用。

不幸的是,它的效果有点太好了。

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

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

6 回答 6

25

我想我已经弄清楚了:如果一个人的缓存清单中有错误(例如,引用的文件不存在),那么 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 请求一个功能,该功能至少可以将格式错误的缓存清单打印到错误控制台。它不应该需要自定义代码附加到这些事件来诊断像重命名文件一样微不足道的问题。

于 2009-11-11T17:07:17.917 回答
16

我使用了HTML5 Rocks 的代码:更新缓存

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);
于 2011-11-21T12:09:30.517 回答
8

我遇到了同样的问题:一旦 Firefox 保存了离线文件,它就永远不会重新加载它们。Chrome 按预期工作,它检查清单文件是否有更改,并在清单文件更改时重新加载所有内容。Firefox 甚至没有从服务器下载清单文件,所以它不会注意到变化。

经过调查,我发现 Firefox 正在缓存缓存清单文件(老式缓存,而不是离线缓存)。设置清单文件的缓存头来Cache-Control: no-cache, private解决问题。

于 2012-03-20T10:34:00.407 回答
7

免责声明:我在清单和缓存方面的经验都是 Safari 和 FF 可能会以不同的方式处理某些事情。

  1. 你说的很对。如果清单中列出了任何找不到的文件,则不会发生缓存。

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

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

总是需要重新加载两次才能看到任何更改。事实上,我有时不得不重新加载 3 次才能看到更新。不知道为什么。

调试时,我使用 php 即时生成清单文件,因此文件名中不会出现拼写错误。我每次也随机生成版本号来强制更新,但仍然有一个离线 webapp 用于测试。

完成后,php 文件可以使用恒定版本号回显已保存的清单数据,并且将始终使用缓存。

只是我最近在玩清单和缓存时学到的一些东西。它工作得很好,但可能会令人困惑。

没有到期。要取消缓存,您必须将清单文件更改为没有任何内容并重新加载。在 Safari 上,清除用户缓存会清除所有缓存的文件。

于 2009-11-13T06:15:18.637 回答
3

我制作了一个 Firefox 插件,它使缓存清单无效并清除 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()
于 2010-09-30T06:55:12.247 回答
2

嗯,我刚刚在缓存上调用了 update(),在对清单文件进行了编辑更改后,收到了检查/下载/准备好的完整序列,重新加载了一次,并在我的一个 js 中进行了文本更改显示在我的应用程序初始页面中的文件立即出现。

看来我只需要重新加载一次。

于 2010-07-04T11:05:14.197 回答