10

为了提高我网站的性能/响应能力,我使用 AJAX、replaceState、pushState 和 popstate 侦听器实现了部分页面加载。

我基本上将页面的中心部分 (HTML) 作为我的状态对象存储在历史记录中。单击链接时,我仅从服务器请求页面的中心位(使用不同的 Accept 标头标识这些请求)并将其替换为 javascript。在 popstate 上,我抓住前一个中心部分并将其推回 dom。

这大部分工作正常,但是我发现了一个我坚持的特定问题。解释起来有点复杂,所以如果不是很清楚,我很抱歉。

我们的大多数页面上都有一个搜索表单。通过 ajax 加载的部分页面仅适用于 GET 请求,并且表单执行 POST 导致整个页面加载。

如果我浏览以下一组页面,我最终会看到一个格式错误的部分页面,该页面包含中心内容,没有任何周围的 dom:

从主页开始(通过整页加载)- 执行搜索(post-redirect-get) 带
您到搜索结果(通过整页加载)- 然后单击主页
返回主页(通过动态获取)- 单击browser back
Search Results (from popstate listener) - 点击浏览器返回
Malformed home page。

当出现格式错误的主页时,我的 popstate 侦听器根本不存在。

认为正在发生的是,浏览器正在缓存主页的第二次加载(动态,部分),然后当整个页面返回时,浏览器仅显示缓存的部分响应而不是整个页面.

为了解决这个问题,我在响应中添加了一个 Vary: Accept 标头,让浏览器知道内容可能会根据接受标头发生变化。我还在部分加载的内容中添加了 Cache-Control max-age=0、pragma no-cache 和过去的到期日期,以试图强制浏览器不缓存它,但这都不能解决它。

不幸的是,我的公司不允许外部流量到我们的开发服务器,所以我无法向您展示这个问题。我在这里查看了各种类似的问题,但它们似乎都不完全相同,建议的解决方案似乎也不起作用。

如果我在我的动态 GET 请求中添加一个无意义的参数 (blah=blah),这可以解决问题。然而,这是一个丑陋的黑客,我宁愿不这样做。这似乎应该可以通过标头解决,因为我认为这是一个缓存问题。谁能解释发生了什么?

4

3 回答 3

9

这是一个缓存问题。将响应标头 Cache-Control 设置为no-cacheormax-age=0时,FF 中不会出现问题(如您所说),但它在 Chrome 中仍然存在。

对我有用的标题是 Cache-Control: no-store。并非所有浏览器都始终如一地实现了这一点(您可以找到询问无缓存和无存储之间有什么区别的问题),但在 Chrome 中也有您期望的结果。

于 2012-07-09T10:31:17.303 回答
1

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

初始路径类似于 /Questions/Show - 加载整个页面并显示第一个问题(问题 0)。当用户单击下一个图像时,它会执行一个带有 url /Questions/Save/0 的 jquery .load() 。这将保存答案并返回包含下一个问题的部分视图。下一次保存使用 /Questions/Save/1 执行 jquery .load() ...

我实现了 History.js,以便用户可以来回前进(前进?)。它将问题编号存储在状态数据中。当它检测到状态变化(并且状态的问题编号与页面上的不同)时,它会执行 jquery .load() 来加载正确的问题。

起初,我使用与加载初始页面时相同的路线(/Questions/Show/X,其中 X 是问题编号)。在后端,我检测它是否是 ajax 请求,如果是,则返回部分视图而不是完整视图。这就是与您的问题类似的问题:假设我在第 3 个问题上,返回,然后前进,然后访问 www.google.com,然后单击返回按钮。它显示了问题 3,但它是部分视图 - 因为浏览器缓存了该路由的部分视图。

我的解决方案是为 ajax 调用创建一个单独的路由:/Questions/Load/X(它在后端使用通用代码)。现在有两个不同的路由(/Questions/Show 用于非 ajax 和 /Questions/Load 用于 ajax),浏览器在上述情况下正确显示整个页面。

所以也许一个类似的解决方案会为你工作......即你的主页有两种不同的路线 - 一种用于完整页面,一种用于部分页面。希望有帮助。

于 2012-11-21T17:10:30.613 回答
1

单击链接时,我仅从服务器请求页面的中心位(使用不同的 Accept 标头标识这些请求)并将其替换为 javascript。

惊人的。这就是 RESTful 的方式。但是要让它发挥作用,还需要做一件事:Vary在响应中添加一个标头。

Vary: Accept

这告诉浏览器具有不同 Accept 标头的请求可能会得到不同的响应。因为这两个请求使用不同的 Accept 标头,所以浏览器(以及任何缓存代理)将分别缓存响应。

与设置不同Cache-Control: no-store,这仍然允许您使用缓存。

于 2014-02-18T19:15:45.067 回答