在单页面应用程序中处理浏览器缓存


27

我试图弄清楚如何正确处理单页应用程序的Web浏览器缓存。

我有一个非常典型的设计:实现SPA的几个HTML,JS和CSS文件,以及SPA消耗的一堆JSON数据。当我要推送更新时会出现问题:我同时更新了网站的静态部分和同时生成JSON的代码,但是客户端浏览器通常缓存了静态部分,因此旧代码尝试处理新数据并可能(取决于所做的更改)遇到问题。(特别是,在使用缓存的JS而无需重新验证的情况下,IE似乎比Chrome或Firefox更具攻击性。)

处理此问题的最佳方法是什么?

  1. 确保我的JSON更改向后兼容,并假定浏览器缓存将在合理的时间范围内到期。
  2. 在静态JS和JSON中都嵌入某种版本号,然后window.location.reload(true);在它们不匹配时执行。
  3. 找出标题的适当组合(must-revalidateno-cache其他方式;有关执行此操作的方法,来源 会有所不同),以确保浏览器始终在每次加载时重新验证所有资源,即使这意味着要进行几次额外的往返加载网站。
  4. 微管理我的缓存控件并使标头过期,以便在我要推送更新时静态内容过期。
  5. 还有吗

1
如果您的环境恶劣(同事咳嗽的 iOS),则听说嵌入式Web浏览器控件中的#3和#4意外失败。#1和#2可以是应用程序级别的选择,但仍然可能会导致其他资源或部分资源负载的缓存问题。我所看到的唯一在生产就绪型代码中可靠工作的方法是获取yoururl.html?<SomeTimeStamp>,因为这会伪造大多数缓存机制。奖励:将整个Web应用程序滚动到一个文件中,以便原子加载成功或失败。缺点:在本地链接上效果最佳。你的旅费可能会改变。祝好运!
J特拉纳2014年

2
+1以使用版本号或时间戳作为资源的URL参数。
9000

Answers:


14

您需要一个缓存清除解决方案。缓存清除的作用是:

  1. 根据资源的内容将其重命名为唯一的名称。
  2. 更新对那些资源的所有引用。

在基于Grunt的项目中,通常使用grunt-rev来确保根据其内容为所有需要刷新的文件赋予唯一的名称。

如果确保您的JSON文件在Javascript中获得了cachebusting文件名以及对其的引用,则客户端将始终加载Javascript期望的JSON文件。

基于哈希的文件命名的优势在于,在清除缓存后,未更改的文件将获得相同的文件名,因此浏览器可以在未更改的情况下继续安全地使用缓存的内容。

显然,这是您要在项目的生产构建中自动化的一种方式,因此您不必跟踪手动更改文件名和引用的情况。


2
斜体的“缓存清除”位为+1,这为有效地实际搜索此内容打开了大门。
扎克·库斯

@Ted Percival-我使用的是yeoman框架,但是我看到了问题。当我发布新版本时,浏览器可能会将index.html缓存了对旧文件的引用...并且浏览器出现错误。我该如何解决?(A.)将所有旧文件名符号链接为新文件名(这是可行的)(B。)将no-cache标头添加到index.html(但这始终受到尊重)(C。)添加.htaccess以识别已修订的文件并搜索基数(即12345.main.js-> main.js)
timh

5

您可以使用if-modified-since + last-modifiedif-none-match + etag标头以及适当的cache-control标头。(可能存在浏览器错误,但在最近的浏览器中无法管理。)

如果文件是静态的,则建议您使用if-modified-since,因为可以使用配置良好的HTTP服务器自动完成。如果自上次下载以来未修改文件,则应发送回304。

我认为您的#1和#2无法长期运作。#3或#4可以工作。#3比较简单,但是您只需学习一次处理该问题的方法。所以如果我是我,我会尝试#4,但是解决方案可能取决于客户使用的浏览器...例如IE8在更新ajax缓存时出现问题,等等。


2

如果可以在SPA中包括Java Servlet过滤器,则可以使用以下解决方案:CorrectBrowserCacheHandlerFilter.java

基本上,当您的浏览器请求静态文件时,服务器会将每个请求重定向到相同的请求,但使用哈希查询参数(?v=azErT例如),该参数取决于目标静态文件的内容。

这样做,浏览器将永远不会缓存在您index.html的示例中声明的静态文件(因为将始终收到302 Moved Temporarily),而只会缓存具有哈希版本的文件(服务器将为200它们回答)。因此,对于具有哈希版本的静态文件,浏览器缓存将得到有效利用。

免责声明:我是的作者CorrectBrowserCacheHandlerFilter.java

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.