如何阻止 Opera 缓存页面?

发布于 2024-09-02 03:29:02 字数 213 浏览 3 评论 0原文

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

如何阻止 Opera 缓存页面?我想要做的是让 Opera 在用户单击浏览器上的“后退”按钮时重新请求页面。

I am trying to get Opera to re-request a page every time instead of just serving it from the cache. I'm sending the 'Cache-control: no-cache' and 'Pragma: no-cache' response headers but it seems as if Opera is just ignoring these headers. It works fine in other browsers - Chrome, IE, Firefox.

How do I stop Opera from caching pages? What I want to be able to do is have Opera re-request a page when the user clicks the Back button on the browser.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

街角卖回忆 2024-09-09 03:29:02

作为用户,我绝对讨厌那些在我使用后退按钮时强制重新加载而减慢历史导航速度的页面。 (如果您每天使用的浏览器关注各种缓存指令,并让它们按照您作为开发人员想要的方式影响历史导航,您可能会注意到某些网站速度变慢......)

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

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

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

As a user, I absolutely detest pages that slow down my history navigation by forcing re-loads when I use the back button. (If the browser you use on a daily basis paid attention to the various caching directives and let them affect history navigation the way you want as a developer you'd probably notice some sites slowing down yourself...)

If you have a very strong use case for doing this I'd say your architecture might be "wrong" in some sense - for example, if you're switching between different "views" of constantly updating data and thus want to enforce re-load when users go back perhaps using Ajaxy techniques for loading the constantly changing data into the current page would be better?

Opera's implementation is on purpose - "caching" is seen as conceptually different from "history navigation", the former is more about storing things on disk and between sessions, the latter is switching back to a temporarily hidden page you just visited, in the state you left it.

However, if you really, really need it there is a loophole in this policy that enables the behaviour you want. Sending "Cache-control: must-revalidate" will force Opera to re-load every page on navigation, but only if you're sending the page over https. (This is a feature requested by and intended for paranoid banks, it slows down way too many normal sites if applied on http).

戴着白色围巾的女孩 2024-09-09 03:29:02

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

It sounds like your problem is related to this answer. After testing your header and the suggested headers, I could only reproduce your expected behavior in Internet Explorer.

怀中猫帐中妖 2024-09-09 03:29:02

简单的服务器端缓存控制,无需标头或前端脚本

零依赖,通用语言版


您可以通过在文件名中附加 md5 或 sha1 校验和,在不使用标头的情况下强制全局重新缓存。

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

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

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

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


这是 RFC 有效标记。请注意,脚本和链接标记有一个获取字符串:

?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: 设置为永久,并且没有太大区别。只要该文件更改了哪怕一个字节,您仍然会立即看到更改。

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

    使用

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

  • 将哈希值作为附加到文件名的 GET 字符串提供给普通文件(例如:styles.css 变为 styles.css?checksum=ba411cafee2f0f702572369da0b765e2

  • 任何更改 重新缓存,这意味着您会立即看到反映的实际值。

    文件中的任何更改都会强制重新缓存,这意味着

  • 您会立即看到反映的实际值。

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

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

SIMPLE SERVERSIDE CACHE CONTROL WITHOUT HEADERS OR FRONTEND SCRIPTS

Zero Dependency, Universal Language Edition


You can force re-caching globally without using a header by appending an md5 or sha1 checksum to your filename.

That way it will cache if it is an exact match, and otherwise treat it like a new resource.

  • Works in all browsers
  • Validates as strict HTML5 (originally did not, but this has been updated. Untested for XHTML, but probably not valid for that)
  • Does not require extra headers
  • Keeps frontend concerns and backend concerns nicely decoupled.
  • Does not require client side sanity checks or source validation.
  • Anything that can print html can do this consistently, including static content
  • If not static, easy to extend runtime control to end users (with authentication, if desired) that allows for simple page flags to determine minified, prettified, or debug source being returned.
  • Entirely encapsulates client cache control in the content serving mechanism, which makes things super simple to maintain.
  • As a side perk, introduces versioned client-side caching automatically by deferring to the checksums the browser has cached, which can be useful if you have alternate versions and need to unit test a release package to determine it's minimum stable dependency versions or something.

  • You don't ever have to fiddle with your browser to get the caching not to interfere with your development process again.

  • This approach also can be used for versioned images, video, audio, pdfs, etc. Pretty much any resource that is served as static data will operate similarly, cache on the first request for the content, and persist automatically without further consideration if the file does not change.


This is RFC valid markup. Notice the script and link tags have a get string:

?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>

The GET string ?checksum=ba411cafee2f0f702572369da0b765e2 refers to either an MD5 or SHA1 hash of the filesize of the resource. It can be obtained through a command line, language construct, or by hashing it from the value of the Content-Length: header. You then construct your href or src attribute by appending it as a GET string to the filename.

This browser will interpret these as distinct, and cache separately.

The server will ignore the GET parameter if it is a static resource, but if it is served dynamically, then the GET parameter will be available to the interpreting language.

This means that whenever that hash changes in the links, the browser will cache that specific version independently one time, and then keep it until forever, or Expires: goes by, whichever is sooner.

Since the checksum is a direct reflection of the filesize, you can set Expires: to forever and it doesn't make much difference. You will still see your changes immediately as soon as that file changes even a single byte.

  • Generate your css or js source with whatever utilities you normally do.

  • Run an md5 or sha1 checksum on the filesize at runtime if you are serving dynamically, and at compiletime if you are generating static content (like ApiGen docs, for example).

  • Serve the normal file with the hash as a GET string appended to the filename (eg: styles.css becomes styles.css?checksum=ba411cafee2f0f702572369da0b765e2)

  • Any change in the file forces a recache, which means you see the real value reflected immediately.

  • Optional, but rad: An additional benefit of this approach is that you can easily set up a dev GET flag, which will make ALL frontend source resolve to prettified dev source with any of your own custom debug functionality enabled, or use it to interpret versioning flags. You can do a redundant check to make sure that flag is only passed from a known development IP address, proxy authentication, etc. by the server and otherwise is not honored if you need it secure. I usually divide my frontend source up whenever possible similar to this:

    • This is what it is doing on live right now (minified production, cached, default, ?checksum=ba411cafee2f0f702572369da0b765e2).
    • This is what it ought to be doing on live right now, prettified enough for me to read (prettified production, never cached, ?debug_pretty_source=true).
    • This is what I use to figure out what isn't doing what it ought to on live if it exists in both of the previous (prettified with debug enabled, never cached, ACL/whitelist authorized, ?debug_dev_enable=true or similar).

You can apply the same principle to package releases by using version numbers instead of checksums, provided your versions don't change. Checksums are less readable but easier to automate and keep in sync with exact changes, but version suffixes are useful for testing package stability also, provided the version number reflects an immutable resource.

爱已欠费 2024-09-09 03:29:02

在寻找解决方案时发现了这个。不高兴,所以写了一些javascript来解决这个问题,这可能对其他人有用。

在任何其他 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 函数中。

演示前后这里还有一些注释。我打算将其添加到我的博客中。我只有几个最新版本的 Opera,所以在我生气之前,我希望先尝试一下演示版。

编辑:刚刚意识到,如果后来访问的站点更改了窗口名称(其持久性),则不会发生后选项卡重新加载。只需将上面的 if 语句更改为:

 if (window.name != "") {

演示在多个选项卡中打开时工作正常;但我依稀记得窗口名称应该是唯一的;所以我修改了演示以生成一个唯一的名称。

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

Found this whilst searching for solution. No joy, so wrote some javascript to solve the problem which may be of use to others.

In <HEAD> above any other 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>

Now change window name so Opera detects it on subsequent load from cache:

window.name = 'previously_loaded';

Insert this line in one of your js blocks that wont be executed during “window load” causing infinite reload. For me there was no need to refresh the page unless someone has exited by a link, so I just added it to my onclick/onunload function.

Before and after demos here with a few more notes. I intend to add it to my blog. I've only a few late versions of Opera, so I would appreciate some tries of the demo before I get egg on my face.

Edit: Just realised that if a later visited site changes window name (its persistent) then back-tab reload wont happen. Just alter above if statement to:

 if (window.name != "") {

Demo worked fine when open in multiple tabs; but I vaguely recollect that window names should be unique; so I've altered the demo to generate a unique name.

window.name = new Date().getTime();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文