HTML5历史记录API返回按钮与部分页面加载

10
为了提高我的网站性能/响应能力,我使用 AJAX、replaceState、pushState 和 popstate 监听器实现了部分页面加载。 我将页面的中央部分(HTML)作为状态对象存储在历史记录中。 当单击链接时,我从服务器请求页面的中央部分(使用不同的 Accept 标头标识这些请求),并使用 JavaScript 替换它。 在 popstate 事件发生时,我获取前一个中央部分并将其推回 dom 中。然而,我发现了一个问题,即当进行 POST 操作时,通过 AJAX 的部分页面加载会出现一些错误。可能是浏览器缓存了第二个动态加载的页面,导致在返回完整页面时仅显示了缓存的部分响应。虽然尝试了添加 Vary: Accept 头和 Cache-Control max-age=0、pragma no-cache 和过期日期等缓存控制方法,但均未解决该问题。

很遗憾,我的公司不允许外部流量访问我们的开发服务器,所以我无法向您展示问题。我查看了这里的各种类似问题,但似乎没有一个完全相同的,并且建议的解决方案似乎也不起作用。

如果我在动态GET请求中添加一个无意义的参数(blah = blah),这样就可以解决问题。然而,这是一种不太好的hack方法,我宁愿不这样做。由于我认为这是一个缓存问题,所以似乎应该通过标头来解决。有人能解释一下这到底是怎么回事吗?


快速更新 - 头部似乎解决了Firefox上的问题,但在Chrome和iOS Safari上仍然存在(可能是Webkit问题?) - Rob Trickey
这听起来像是缓存问题。在动态GET请求中添加一个参数似乎是合理的 - 这就是jquery-pjax所做的。 - Sean Hogan
3个回答

9
这是缓存问题。当响应头Cache-Control设置为no-cachemax-age=0时,在FF中(如您所说)不会出现问题,但在Chrome中问题仍然存在。
对我有效的标头是Cache-Control:no-store。这并不是所有浏览器都一致实现的(您可以找到一些问题询问no-cache和no-store之间的区别),但在Chrome中也能得到您期望的结果。

1
当单击链接时,我会使用不同的Accept头标识这些请求,从服务器中仅请求页面的中央部分,并用JavaScript替换它。很棒,这是RESTful的方式。但还有一件事要做才能使其正常工作:在响应中添加Vary标头。
Vary: Accept

那告诉浏览器,使用不同的Accept头可能会得到不同的响应。因为这两个请求使用不同的Accept头,浏览器(以及任何缓存代理)将单独缓存响应。与设置Cache-Control: no-store不同,这仍然允许您使用缓存。

1

我遇到了类似的问题。我正在构建一个基于Web的向导,并使用jquery ajax加载每个步骤(后端为ASP.NET MVC)。

最初的路由类似于/Questions/Show-它加载整个页面并显示第一个问题(问题0)。当用户单击下一张图片时,它会使用url /Questions/Save/0进行jquery .load()。这将保存答案并返回下一个问题的部分视图。下一个保存将使用jquery .load()和/Questions/Save/1 ...

我实现了History.js,以便用户可以前进和后退。它在状态数据中存储问题编号。当它检测到状态更改(并且状态的问题编号与页面上的不同),它会使用jquery .load()加载正确的问题。

起初,我使用与初始页面加载时相同的路由(/Questions/Show/X,其中X是问题编号)。在后端,我检测到它是否为ajax请求,如果是,则返回部分视图而不是完整视图。这就是类似于您遇到的问题:假设我正在第3个问题上,然后回退,然后前进,然后转到www.google.com,然后点击后退按钮。它显示了第3个问题,但它是部分视图-因为浏览器缓存了该路由的部分内容。
我的解决方案是为ajax调用创建一个单独的路由:/Questions/Load/X(它在后端使用通用代码)。现在有两个不同的路由(/Questions/Show用于非ajax和/Questions/Load用于ajax),在上述情况下,浏览器正确显示完整页面。
所以也许一个类似的解决方案对您有用……即主页的两个不同路由-一个用于完整页面,另一个用于部分页面。希望能帮到您。

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