如何阻止Opera缓存页面?

时间:2010-05-19 15:16:47

标签: caching opera

我试图让Opera每次都重新请求一个页面,而不是仅仅从缓存中提供它。我正在发送'Cache-control:no-cache'和'Pragma:no-cache'响应头,但似乎Opera只是忽略了这些头。它在其他浏览器中运行良好 - Chrome,IE,Firefox。

如何阻止Opera缓存页面?我希望能够做的是当用户点击浏览器上的“后退”按钮时,Opera会重新请求页面。

4 个答案:

答案 0 :(得分:7)

作为一个用户,我绝对讨厌通过在我使用后退按钮时强制重新加载来减慢历史导航速度的页面。 (如果您每天使用的浏览器注意到各种缓存指令,并让它们以您希望的方式影响历史导航,那么您可能会注意到某些网站会让您自己放慢速度......)

如果您有一个非常强大的用例,我会说您的架构在某种意义上可能是“错误的” - 例如,如果您在不断更新数据的不同“视图”之间切换,因此希望当用户返回时强制重新加载,或许使用Ajaxy技术将不断变化的数据加载到当前页面会更好吗?

Opera的实现是有目的的 - “缓存”在概念上与“历史导航”不同,前者更多的是将内容存储在磁盘上和会话之间,后者切换回刚刚访问过的临时隐藏页面,在你离开它的状态。

但是,如果您确实需要它,那么此策略中存在一个漏洞,可以实现您想要的行为。发送“缓存控制:必须重新验证”会强制Opera重新加载导航中的每个页面,但如果您通过https发送页面,则。 (这是偏执银行要求并打算使用的功能,如果应用于http,它会减慢太多正常网站的速度。)

答案 1 :(得分:2)

听起来您的问题与this answer有关。在测试了标题和建议的标题后,我只能在Internet Explorer中重现您的预期行为。

答案 2 :(得分:2)

没有标题或前端脚本的简单服务器缓存控制

零依赖,通用语言版

您可以通过在文件名后附加md5或sha1校验和来强制全局重新缓存而不使用标头。

这样,如果它是完全匹配,它将缓存,否则将其视为新资源。

  • 适用于所有浏览器
  • 验证为严格的HTML5 (最初没有,但已更新。未经测试的XHTML,但可能无效)
  • 不需要额外的标题
  • 保持前端问题和后端问题很好地解耦。
  • 不需要客户端健全性检查或来源验证。
  • 任何可以打印html的内容都可以一致地执行此操作,包括静态内容
  • 如果不是静态的,很容易将运行时控制扩展到最终用户(带有身份验证,如果需要),它允许使用简单的页面标志来确定返回的缩小,美化或调试源。
  • 完全将客户端缓存控制封装在内容服务机制中,这使得维护起来非常简单。
  • 作为副作用,通过推迟浏览器缓存的校验和自动引入版本化客户端缓存,如果您有备用版本并需要进行单元测试,这将非常有用发布包以确定它的最小稳定依赖版本或类似内容。

  • 您不必 必须摆弄浏览器以获得缓存,以免再次干扰您的开发过程。

  • 这种方法也可以用于版本化的图像,视频,音频,pdf等。几乎任何作为静态数据的资源都会以类似的方式运行,在第一次内容请求时缓存,并自动保留如果文件没有改变,则无需进一步考虑。

这是RFC有效标记。请注意,脚本和链接标记具有get字符串:

?checksum=ba411cafee2f0f702572369da0b765e2

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">

  <title>Client Cache Control Example</title>
  <meta name="description" content="You're only going to cache this when the content changes, and always when the content changes.">
  <meta name="author" content="https://stackoverflow.com/users/1288121/mopsyd">

  <!-- Example Stylesheet -->
  <link rel="stylesheet" href="css/styles.css?checksum=ba411cafee2f0f702572369da0b765e2">

  <!-- Example Script -->
  <script src="js/scripts.js?checksum=ba411cafee2f0f702572369da0b765e2"></script>
</head>
<body>
</body>
</html>

GET字符串?checksum=ba411cafee2f0f702572369da0b765e2是指资源文件大小的MD5或SHA1哈希值。它可以通过命令行,语言构造或通过从Content-Length:标头的值进行散列来获得。然后,通过将其作为GET字符串附加到文件名来构造hrefsrc属性。

此浏览器会将这些解释为不同的,并单独缓存。

如果GET参数是静态资源,服务器将忽略它,但如果它是动态提供的,那么GET参数将可用于解释语言。

这意味着只要链接中的哈希值发生变化,浏览器就会独立地一次缓存该特定版本,然后将其保留到永久,或者Expires:过去,无论哪个是越快。

由于校验和是文件大小的直接反映,因此您可以将Expires:设置为永久,但它并没有太大的区别。只要该文件改变一个字节,您仍会立即看到您的更改。

  • 使用您通常使用的任何实用程序生成css或js源。

  • 如果要动态提供,则在文件大小运行时运行md5或sha1校验和;如果要生成静态内容,则在编译时运行比如ApiGen文档,例如

  • 将带有散列的普通文件作为附加到文件名的GET字符串提供(例如:styles.css变为styles.css?checksum=ba411cafee2f0f702572369da0b765e2

  • 文件中的任何更改都会强制重新缓存,这意味着您会立即看到实际值。

  • 可选,但是rad:此方法的另一个好处是,您可以轻松设置一个dev GET标志,这将使所有前端源解析为使用任何您自己的自定义调试功能已启用,或使用它来解释版本控制标志。您可以执行冗余检查以确保标志仅由服务器从已知的开发IP地址,代理身份验证等传递,否则如果您需要它,则不会受到尊重。我通常会尽可能地将我的前端源分开:

    • 这就是它现在正在做的事情(缩小制作,缓存,默认,?checksum=ba411cafee2f0f702572369da0b765e2)。
    • 这就是它现在应该在现场做的事,足以让我阅读(美化生产,never cached?debug_pretty_source=true)。
    • 这就是我用来弄清楚如果它存在于以前的两个中都没有做它应该做的事情(已启用调试,never cached,ACL /白名单授权,{ {1}} 或类似)。

如果您的版本没有更改,您可以使用版本号而不是校验和来应用相同的原则来打包版本。校验和的可读性较差,但更容易自动化并与精确更改保持同步,但版本后缀对于测试包稳定性也很有用,前提是版本号反映了不可变资源。

答案 3 :(得分:0)

在寻找解决方案时找到了这个。没有快乐,所以写了一些javascript来解决可能对他人有用的问题。

<HEAD>以上任何其他javascript:

<script>
    if( typeof(opera) != 'undefined' ) { // only do for Opera
       if (window.name == 'previously_loaded') { // will be "" before page is loaded
            alert('Reloading Page from Server'); // for testing
            window.name = ''; // prevent multiple reload
            window.location.reload(true);
       }
    }
</script>

现在更改窗口名称,以便Opera在后续从缓存加载时检测到它:

window.name = 'previously_loaded';

在“窗口加载”期间不会执行的一个js块中插入此行,从而导致无限重新加载。对我来说,没有必要刷新页面,除非有人通过链接退出,所以我只是将它添加到我的onclick / onunload函数。

Before and after demos 此处还有一些说明。我打算将它添加到我的博客中。我只有几个晚期版本的Opera,所以在我得到鸡蛋之前,我会很感激一些演示尝试。

编辑:刚刚意识到如果以后访问过的网站更改了窗口名称(其持久性),那么后退标签重新加载就不会发生。只需将上述声明改为:

 if (window.name != "") {

在多个标签中打开时,演示工作正常;但我含糊地回忆起窗口名称应该是唯一的;所以我改变了演示以生成一个唯一的名称。

window.name = new Date().getTime();