从缓存中加载window.location.reload和散列片段在Chrome不工作

Load from cache with window.location.reload and hash fragment in Chrome doesn't work

本文关键字:片段 Chrome 工作 缓存 加载 window reload location      更新时间:2023-09-26

我需要用Javascript重新加载页面。出于这个目的,我使用window.location.reload。现在,我在Chrome中观察到一个奇怪的行为:Chrome总是连接到服务器并询问文档是否被修改。虽然返回了一个304 Not Modified,但仍然有一个到服务器的往返,这是我想要避免的。

我也尝试明确使用window.location.reload(false)告诉chrome使用缓存,但没有成功。并不是说我在重新加载的url中有一个活动的哈希(#)片段。

资源的响应头如下:

HTTP/1.1 304 Not Modified
Server: nginx/1.2.2
Date: Sat, 01 Jun 2013 13:19:56 GMT
Last-Modified: Sat, 01 Jun 2013 13:04:55 GMT
Connection: keep-alive
Expires: Sun, 02 Jun 2013 13:19:56 GMT
Cache-Control: max-age=86400
Access-Control-Allow-Origin: *

所以,Cache-ControlExpires头都设置了,应该告诉chrome不要在24小时内更新资源。

我不使用F5/CMD+R重新加载页面,而是点击一个链接,这将有一个javascript事件,将改变window.location.hash,然后调用window.location.reload(false)。但Chrome一直设置Cache-Control: max-age=0头的请求-这是我不想要的。Chrome应该使用它的内部缓存,根本不向服务器发送任何东西。

同样的代码使用Firefox是没有问题的,FF使用缓存的版本而不连接到服务器。

我该如何解决这个问题?

编辑:这里有一个简单的例子,你可以用它来试用自己:http://webspace.markdown.io/reloadtest.html

编辑:我已经关闭了开发人员工具,并通过服务器上的tcpdump -s 1024 -l -A dst port 80验证头。我还在开发人员工具中取消了"禁用浏览器缓存"。

编辑2:请注意,如果关闭选项卡并输入新的Url, Chrome将正确使用缓存。只有点击链接(这将导致window.location.reload受到影响)

在做了更多的研究之后,我自己回答:

这是不可能的。

这个问题与hash值完全无关,即使不使用散列也会出现。

似乎window.location.reload()不能用来控制当前资源(由window.location.href指示)是否从缓存中使用。尽管MDN上的文档显示并非如此。window对象中Location对象的官方W3C规范也没有多大帮助。

Chrome和Firefox将总是执行到服务器的往返,请求当前资源,无论您传递给.reload()的参数是什么。该参数最初是为了强制POST请求作为GET请求重复而引入的——这与缓存无关。(使用Firebug时要小心:我首先认为FF不会发送请求,因为它没有显示在Firebug中-但是当你查看web服务器日志时,你可以看到它实际上是这样做的)。

我可以观察到布尔参数的存在会影响浏览器是否将Cache-Control: max-age=0标头附加到请求。但这只会减少传输的数据,根本不会消除服务器连接。在任何情况下都要进行往返。

在最新的HTML5草案中(很可能不经修改成为最终的HTML5标准),location.reload()函数不再接受任何布尔参数。因此,当你瞄准HTML5时,你不应该以任何方式依赖于这个参数。

你可以这样做:

function reload_page() {
    window.location.hash = new Date().getTime();
    window.location.replace(window.location.href);
    loaded();
}
window.onload = loaded;
function loaded() {
    document.getElementById('thetime').innerHTML = new Date().toISOString();
}

使用F5或window.location.reload重新加载页面,即使从其他页面导航到该页面将直接在缓存中查找,也会建立网络连接。虽然reload(true)强制它绕过缓存(从服务器获取200而不是304),但reload(false)并不强制它在决定是否需要连接到服务器之前查看缓存。

如果浏览器不会在缓存中重新加载页面,并且当链接后面只有片段不同时,它不会重新加载页面,试着让它认为它正在加载不同的页面以使它在缓存中查找。它使用ajax(从缓存)获取您正在查看的页面,并用它替换整个文档。然后它用一个新的URI片段替换URI片段——以这种方式更改片段会触发JavaScript框架中的任何函数侦听片段中的更改。

<html>
<head>
    <script src="http://code.jquery.com/jquery-1.8.1.min.js"></script>
</head>
<body>
    <p>
        It is: <span id="thetime"></span>
    </p>
    <a href="javascript: reload_page()">Reload</a>
    <script type="text/javascript">
        function reload_page() {
            var hash = new Date().getTime()
            $.get(window.location, function(data) {
                var newDoc = document.open("text/html", "replace");
                newDoc.write(data);
                newDoc.close();
                window.location.hash = new Date().getTime();
            });
        }
        document.getElementById('thetime').innerHTML = new Date().toISOString();
    </script>
</body>
</html>