如何在Firefox中防止从“后退-前进”缓存中显示内容?

17

浏览器:Firefox 6.0

我有一个页面A,采用以下设置来确保内容不被存储在浏览器的bfcache中:

1)$(window).unload(function(){});

2)遵循HTTP头:

<meta http-equiv="pragma" content="no-cache" /> 
<meta http-equiv="expires" content="-1" />
<meta http-equiv="cache-control" content="no-cache"/>
我还连接了pagehidepageshow事件。 当我离开页面时,pagehide会调用,并使用正确的事件属性值persisted = false(这是需要的:不保留缓存!)
浏览了几页后,我使用window.history.go(-2);回到页面A。此时,我希望Firefox轮询服务器以获取更新版本,而不是从缓存中显示。 Page A的pageshow与事件属性persisted = false的正确值一起调用(表示未从缓存加载页面)。 但是页面内容不是服务器数据; 它是旧的内容(与最初离开页面时相同)! Fiddler也没有显示新的服务器请求。
Google Chrome也表现出相同的行为。 IE按预期工作(重新加载新数据)!
有任何想法吗?
先感谢您!
5个回答

14

有多个缓存参与其中,包括浏览器的文档缓存(bfache)、浏览器的HTTP缓存,以及可能的中间HTTP缓存。

您上面展示的<meta>标签在当前版本的Chrome或Firefox中完全没有任何效果。它们可能在IE中有影响。

所以很有可能,您的页面只是从浏览器的HTTP缓存中读取。

如果您真的想发送不缓存的HTTP头,那么您应该这样做。但它们需要是实际的HTTP头:正如我之前所说,<meta>标签的“等效物”没有任何作用。

重要的是,任何其他中间缓存都不会解析您的HTML,因此如果您没有实际发送正确的HTTP头,则可能会缓存内容。


6
谢谢!以下的HTTP头信息已经可用:`Cache-Control: no-cache Pragma: no-cache Expires: -1`不幸的是,它们并没有起到帮助的作用。在收到您的回复后,我重新检查了头信息,并发现Firefox需要另一个头信息来防止缓存:http://blog.httpwatch.com/2008/10/15/two-important-differences-between-firefox-and-ie-caching/`Cache-Control: no-cache, no-store`添加了上述头信息之后,在IE、Firefox、Chrome和Safari中都能正常工作。只有Opera仍然会出现缓存问题,但我暂时将其推迟处理。 - Venkat
另外需要注意的是:如果网站启用了SSL,Firefox将不会在bfcache中存储!我的生产系统是SSL,而开发系统则没有。因此,在Firefox中,生产系统可以正常工作,无需任何额外的HTTP头文件,如上所述! - Venkat
这取决于你的HTTP头。SSL + no-cache不会被存储在bfcache中,但可缓存的SSL将被存储。 - Boris Zbarsky
正确!在我的情况下,“no-cache”头已经存在。我所说的“附加HTTP头”是指“no-store”头;如果使用SSL,则不需要该头! - Venkat

8
如果您在http头中设置Cache-Control: "no-cache, no-store, must-revalidate",则该页面将不会被缓存在后退/前进缓存中。
Firefox 还将beforeunload事件上的事件处理程序视为不将页面存储在BFC中的信号,但Safari会忽略此类处理程序,因此最好设置正确的http头以指示页面内容的性质(可缓存或变量)。

1
非常感谢您,在我经过三天的研究后,您拯救了我! - Brian Cannard
HTTP头只影响普通缓存,而不影响bfcache(在Firefox中)。为了确保,您需要设置头并设置“unload”事件。当按下后退按钮时,Firefox将使用bfcache,如果不起作用,则回退到普通缓存,因此您需要确保页面不会同时被缓存在两个地方。 - Flimm

4

请注意有两个缓存:

bfcache(前后缓存)

bfcache(在Firefox、Safari和Chrome中)将页面及其DOM的任何动态修改存储在内存中。当按下后退按钮时,Firefox、Safari和Chrome会使用它。为了尝试确保页面不存储在此缓存中,您需要运行以下代码:

window.addEventListener('unload', function(){});
window.addEventListener('beforeunload', function(){});

请注意,这似乎在桌面版Firefox和Chrome中有效,但不总是在桌面版Safari、Android Chrome或Android Firefox或iOS Safari中有效。
请注意,Webkit文档将bfcache称为“页面缓存”。
常规浏览器缓存
除非您在Cache-Control标题中设置适当的no-store值,否则页面将被缓存在常规浏览器缓存中。为了更加确保,请发送完整的标题。
Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private

当按下后退按钮时,Firefox、Safari和Chrome首先会检查bfcache,然后再回退到正常的缓存。因此,您需要同时添加一个事件侦听器到unload,并设置此Cache-Control HTTP头。请注意,使用<meta>而不是HTTP头可能无法正常工作。

参考资料:


使用 window.addEventListener('unload', function(){}); 或者 window.onunload = function(){}; 或者 window.onbeforeunload = function(){}; 有什么区别吗? - Kevin Wheeler
@KevinWheeler 这三个都有可能在某些浏览器中禁用 bfcache。请参见 https://web.dev/bfcache/ - Flimm

3

下面的答案已经过时:

SO上的回答中,给window添加一个unload事件会导致后退/前进缓存被清除。

更新。可能的解决方案:

BFCache可能会给开发人员带来惊喜,因为至少在Firefox中,即使HTTP头告诉它刷新页面,当返回/前进时页面也不会刷新。所以最好假设页面不会刷新

另一方面,因为BFCache获取到过时数据的页面和在你的浏览器中找到长时间未重新加载的选项卡有何区别呢?

如果您关心这些事情,请编写一些JavaScript代码来检查服务器是否有更新并重新加载敏感信息。这是将问题转化为胜利的机会 : )。


后退/前进缓存 === bfcache - Dan
1
我无法通过向窗口添加unload事件来使bfcache失效,例如window.onunload = function () { console.log('lets unload windows');}。您能否更具体地说明如何操作?非常感谢。 - Simon
我尝试了http://www.jakearchibald.com/jsperformance/backforwardcache/上的示例,结果发现它也不起作用。 - Simon
1
我尝试了 $(window).unload(function(){});,但仍然从浏览器缓存加载页面。 - murtza gondal
HTTP头只影响普通缓存,而不影响bfcache(在Firefox中)。为了确保更加安全,您需要设置头并设置“unload”事件。当按下后退按钮时,Firefox将使用bfcache,如果这不起作用,则回退到普通缓存,因此您需要确保页面不会同时被缓存在两个地方。 - Flimm

0
不确定现在这对你来说是否相关,但可能有人会来这里寻找解决方案。
以下是一种检查页面是否从 bfcache 加载的方法,根据这个可以根据需要进行执行。
          window.addEventListener('pageshow', (event) => {
            if (event.persisted) {
              console.log('This page was restored from the bfcache.');
              location.reload();
            } else {
              console.log('This page was loaded normally.');
            }
          });

你可以在https://web.dev/bfcache/上阅读更多相关信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接