强制浏览器在站点更新后重新加载所有缓存



是否有一种方法可以强制网页的客户端重新加载缓存(即图像,javascript等)后,服务器已推送更新到代码库?我们接到很多求助电话,询问为什么某些功能不再工作。一个简单的硬刷新修复问题,因为它下载了新更新的javascript文件。

具体我们使用的是Glassfish 3.x。和JSF 2.1.x。当然,这不仅仅适用于JSF。

描述我希望什么行为是可能的:

网站A有两个图片和两个javascript文件。用户访问该站点,4个文件被缓存。就我而言,没有必要"重新下载"上述文件,除非用户特别强制"硬"刷新或清除他们的缓存。一旦站点将更新推送到其中一个文件,服务器可以在报头中提供某种元数据,通知客户端所述更新。如果客户端选择,新文件将被下载。

我不想做的是在页面的标题中放置meta-tag来强制任何东西都不被缓存…我只是想要的东西,告诉客户端一个更新已经发生,它应该得到最新的东西已经更新。我想这只是客户端的某种版本控制。

谢谢你的时间!

处理这个问题的正确方法是更改资源的URL约定。例如,我们把它写成:

/resources/js/fileName.js

要让浏览器仍然缓存文件,但要以正确的方式进行版本控制,可以在URL中添加一些内容。向querystring添加值不允许缓存,因此将其放置在/resources/之后。

查询字符串缓存的参考:http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9

例如,你的url是这样的:

/resources/1234/js/fileName.js

所以你可以做的是使用项目的版本号(或者当你想要重新加载缓存文件时手动更改的属性/配置文件中的一些值),因为这个数字应该只有在项目被修改时才会改变。所以你的URL可以像这样:

/resources/cacheholder${project.version}/js/fileName.js

这应该很容易。

现在的问题是映射URL,因为中间的值是动态的。我们克服这个问题的方法是使用一个URL重写模块,它允许我们在URL到达应用程序之前对它们进行过滤。重写过程监视如下url:

/resources/cacheholder______/whatever

并去除cacheholder_______/部分。重写后,它看起来像一个正常的请求,服务器将响应正确的文件,没有任何其他特定的映射/逻辑…关键是浏览器认为它是一个新文件(即使它实际上不是),所以它请求它,服务器发现它并提供正确的文件(即使它是一个"奇怪"的URL)。

当然,另一种选择是将这个动态字符串添加到文件名本身,然后使用重写工具删除它。无论哪种方式,完成的事情都是一样的——在重写期间针对文本字符串并删除它。这样可以骗过浏览器,但骗不了服务器:)


更新:

我真正喜欢的另一种方法是基于内容设置文件名,并缓存它。例如,这可以用散列来完成。当然,这种类型的事情不是你手动完成并保存到你的项目(希望如此);这是应用程序/框架应该处理的事情。例如,在Grails中,有一个"散列和缓存"资源的插件,因此会发生以下情况:

  • 每个资源都被检查
  • 创建一个新文件(或到该文件的映射),其名称是其内容的散列
  • 当添加<script>/<link>标签到您的页面时,使用散列名称
  • 当请求哈希命名文件时,它服务于原始资源
  • 哈希命名文件被"永远"缓存

这个设置的酷之处在于,你不必担心缓存是否正确——只需要将文件设置为永久缓存,并且哈希应该根据内容处理文件/映射是否可用。它还提供了快速缓存和加载回滚/撤销的能力。

对于这种情况,我使用no-cache参数…A有一个字符串常量值,如(从配置文件)

$no_cache = "v11";

在页面中,我使用像

这样的资产
<img src="a.jpg?nc=$no_cache">

,当我更新我的代码,只要改变$no_cache的值,它就像一个魅力。

最新更新