我试图弄清楚如何正确处理单页应用程序的Web浏览器缓存。
我有一个非常典型的设计:实现SPA的几个HTML,JS和CSS文件,以及SPA消耗的一堆JSON数据。当我要推送更新时会出现问题:我同时更新了网站的静态部分和同时生成JSON的代码,但是客户端浏览器通常缓存了静态部分,因此旧代码尝试处理新数据并可能(取决于所做的更改)遇到问题。(特别是,在使用缓存的JS而无需重新验证的情况下,IE似乎比Chrome或Firefox更具攻击性。)
处理此问题的最佳方法是什么?
我试图弄清楚如何正确处理单页应用程序的Web浏览器缓存。
我有一个非常典型的设计:实现SPA的几个HTML,JS和CSS文件,以及SPA消耗的一堆JSON数据。当我要推送更新时会出现问题:我同时更新了网站的静态部分和同时生成JSON的代码,但是客户端浏览器通常缓存了静态部分,因此旧代码尝试处理新数据并可能(取决于所做的更改)遇到问题。(特别是,在使用缓存的JS而无需重新验证的情况下,IE似乎比Chrome或Firefox更具攻击性。)
处理此问题的最佳方法是什么?
Answers:
您需要一个缓存清除解决方案。缓存清除的作用是:
在基于Grunt的项目中,通常使用grunt-rev来确保根据其内容为所有需要刷新的文件赋予唯一的名称。
如果确保您的JSON文件在Javascript中获得了cachebusting文件名以及对其的引用,则客户端将始终加载Javascript期望的JSON文件。
基于哈希的文件命名的优势在于,在清除缓存后,未更改的文件将获得相同的文件名,因此浏览器可以在未更改的情况下继续安全地使用缓存的内容。
显然,这是您要在项目的生产构建中自动化的一种方式,因此您不必跟踪手动更改文件名和引用的情况。
您可以使用if-modified-since + last-modified
或if-none-match + etag
标头以及适当的cache-control
标头。(可能存在浏览器错误,但在最近的浏览器中无法管理。)
如果文件是静态的,则建议您使用if-modified-since
,因为可以使用配置良好的HTTP服务器自动完成。如果自上次下载以来未修改文件,则应发送回304。
我认为您的#1和#2无法长期运作。#3或#4可以工作。#3比较简单,但是您只需学习一次处理该问题的方法。所以如果我是我,我会尝试#4,但是解决方案可能取决于客户使用的浏览器...例如IE8在更新ajax缓存时出现问题,等等。
如果可以在SPA中包括Java Servlet过滤器,则可以使用以下解决方案:CorrectBrowserCacheHandlerFilter.java
基本上,当您的浏览器请求静态文件时,服务器会将每个请求重定向到相同的请求,但使用哈希查询参数(?v=azErT
例如),该参数取决于目标静态文件的内容。
这样做,浏览器将永远不会缓存在您index.html
的示例中声明的静态文件(因为将始终收到302 Moved Temporarily
),而只会缓存具有哈希版本的文件(服务器将为200
它们回答)。因此,对于具有哈希版本的静态文件,浏览器缓存将得到有效利用。
免责声明:我是的作者CorrectBrowserCacheHandlerFilter.java
。