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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1715568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 01:16:55  来源:igfitidea点击:

How to properly invalidate an HTML5 Cache Manifest for online/offline web apps?

firefoxcachinghtmloffline-caching

提问by Justin Searls

I'm currently using a Cache Manifest (as described here). This effectively makes the necessary resources to run the application available when the user is offline.

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

Unfortunately, it works a little too well.

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

After the cache manifest is loaded, Firefox 3.5+ caches all of the resources explicitly referenced in the cache manifest. However, if a file on the server is updated and the user tries force-refreshing the page while online (including the cache-manifest itself), Firefox will absolutely refuse to fetch anything. The application remains completely frozen at the last point it was cached. Questions:

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

  1. I want Firefox to effectively only rely on the cached resources when the network connection fails. I've tried using the FALLBACK block, but to no avail. Is this even possible?
  2. If #1 is not possible, is it possible for the user to force-refresh a page and bypass this cache (ctrl-F5 doesn't do it and neither does clearing the browser's cache, shockingly) short of clearing their private data? Alternatively, does the cache-manifest mechanism support expiry headers and is its behavior with respect to this documented anywhere?
  1. 我希望 Firefox 在网络连接失败时有效地只依赖缓存的资源。我试过使用 FALLBACK 块,但无济于事。这甚至可能吗?
  2. 如果#1 是不可能的,用户是否有可能强制刷新页面并绕过这个缓存(ctrl-F5 不这样做,也没有清除浏览器的缓存,令人震惊)没有清除他们的私人数据?或者,缓存清单机制是否支持过期标头,它的行为是否记录在任何地方?

采纳答案by Justin Searls

I think I've got this figured out: if there's an error in one's cache-manifest (say, a referenced file does not exist), then Firefox completely will stop processing anything applicationCache related. Meaning, it won't update anything in your cache, including your cached cache-manifest.

我想我已经弄清楚了:如果一个人的缓存清单中有错误(例如,引用的文件不存在),那么 Firefox 将完全停止处理与 applicationCache 相关的任何内容。意思是,它不会更新缓存中的任何内容,包括缓存的缓存清单。

To uncover that this was the issue, I borrowed some code from Mozillaand dropped this into a new (non-cached) HTML file in my application. The final message logged stated that there might be a problem in my cache-manifest, and sure enough there was (a missing file).

为了发现这是问题所在,我从 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 }

This was certainly helpful, but I should definitely request a feature from Mozilla that prints out malformed cache-manifests at least to the Error Console. It shouldn't require custom code to attach to these events to diagnose an issue as trivial as a renamed file.

这当然很有帮助,但我绝对应该要求 Mozilla 提供一项功能,该功能至少可以将格式错误的缓存清单打印到错误控制台。它不应该需要自定义代码来附加到这些事件来诊断与重命名文件一样微不足道的问题。

回答by Danubian Sailor

I've used code from HTML5 Rocks: Update the cache:

我使用了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);

回答by OlliM

I had the same problem: once Firefox saved the offline files, it would not reload them ever. Chrome worked as expected, it checked the manifest file for changes and reloaded everything if the manifest file changed. Firefox didn't even download the manifest file from the server, so it could not notice changes.

我遇到了同样的问题:一旦 Firefox 保存了离线文件,它就不会重新加载它们。Chrome 按预期工作,它检查清单文件是否有更改,如果清单文件更改,则重新加载所有内容。Firefox 甚至没有从服务器下载清单文件,因此它无法注意到更改。

After investigation, I found out that Firefox was caching the cache manifest file (old fashioned cache, not the offline cache). Setting the cache header of the manifest file to Cache-Control: no-cache, privatesolved the problem.

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

回答by GeoNomad

Disclaimer: my experience with manifests and cache is all Safari and FF may handle some things differently.

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

  1. You are quite right. If there are any files listed on the manifest that can't be found, no caching will occur.

  2. Even if you are online, the browser will check only the manifest file. While waiting for the manifest file, it will continue to load the site from the cache - that way it doesn't delay rendering - but it means that you don't see any changes on the first load.

  3. The next time the site is loaded, if the manifest changed on the previous load, the new files will be loaded.

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

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

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

IT IS ALWAYS NECESSARY TO RELOAD TWICE to see any changes. In fact, I have sometimes had to reload 3 times to see the update. No idea why.

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

When debugging, I generate my manifest file on the fly with php, so there is no chance of a typo in a filename. I also generate the version number randomly each time to force an update but still have an offline webapp for testing.

调试时,我使用 php 即时生成我的清单文件,因此文件名中不可能出现拼写错误。我每次也随机生成版本号以强制更新,但仍然有一个离线 web 应用程序进行测试。

Once complete, the php file can just echo the saved manifest data with a constant version number and the cache will always be used.

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

Just some things I have learned while playing with manifest and cache recently. It works great, but can be confusing.

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

There is no expiry. To uncache, you have to change the manifest file to have nothing in it and do a reload. On Safari, clearing the user cache does clear out all cached files.

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

回答by keigoi

I made an Firefox add-on which invalidates the Cache Manifest and clears HTML5 Local Storage.

我制作了一个 Firefox 插件,它使缓存清单无效并清除 HTML5 本地存储。

http://sites.google.com/site/keigoattic/home/webrelated#TOC-Firefox-HTML5-Offline-Cache-and-Loc

http://sites.google.com/site/keigoattic/home/webrelated#TOC-Firefox-HTML5-Offline-Cache-and-Loc

You can also invalidate the cache manifest by typing the code below in the Error Console:

您还可以通过在错误控制台中键入以下代码来使缓存清单无效:

// 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();

Or, by typing the code below in the address bar will manually enforece the cache to be updated:

或者,通过在地址栏中键入以下代码将手动强制更新缓存:

javascript:applicationCache.update()

回答by BobFromBris

Hmm, I just called update() on the cache, after making an edit change to the manifest file, and received the full sequence of check/downloading/ready, did one reload, and a text change I had made in one of my js files, that shows up in the initial page of my app, promptly appeared.

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

Seems I only need one reload.

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