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

时间:2013-04-10 20:46:56

标签: javascript web-applications deployment glassfish-3 cache-control

在服务器被推送到代码库的更新后,是否有办法强制网页的客户端重新加载缓存(即图像,javascript等)?我们收到很多帮助台电话询问为什么某些功能不再有效。一个简单的硬刷新修复了下载新更新的javascript文件时的问题。

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

描述我希望可行的行为:

网站A有两个图片和两个javascript文件。用户访问该站点并缓存4个文件。就我而言,除非用户专门强制“硬”刷新或清除其缓存,否则无需“重新下载”所述文件。一旦站点被推送到其中一个文件的更新,服务器可以在标题中具有某种元数据,通知客户端所述更新。如果客户选择,则会下载新文件。

我不想做的是将meta-tag放在页面的标题中以强迫任何东西不被缓存......我只是想要一些告诉客户端已经发生更新的东西,它应该得到最新的一旦更新了什么。我想这只是客户端的某种版本。

谢谢你的时间!

2 个答案:

答案 0 :(得分:12)

处理此问题的正确方法是更改​​资源的URL约定。例如,我们将其作为:

/resources/js/fileName.js

要让浏览器仍然缓存文件,但是通过版本控制以正确的方式执行,是通过向URL添加内容。向查询字符串添加值不允许缓存,因此放置它的位置在/resources/之后。

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

例如,您的网址如下所示:

/resources/1234/js/fileName.js

所以你可以做的是使用项目的版本号(或者当你想要重新加载缓存文件时手动更改的属性/配置文件中的某个值),因为这个数字仅更改当项目被修改时。所以你的网址可能如下:

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

这应该很容易。

现在的问题是映射URL,因为中间的值是动态的。我们克服的方式是使用URL重写模块,允许我们在到达应用程序之前过滤URL。对于看起来像这样的URL的重写进行了重写:

/resources/cacheholder______/whatever

删除了cacheholder_______/部分。在重写之后,它看起来像一个正常的请求,服务器将使用正确的文件进行响应,而没有任何其他特定的映射/逻辑...重点是浏览器认为它是一个新文件(即使它真的不是' t),所以它请求它,并且服务器将其计算出来并提供正确的文件(即使它是一个“奇怪的”URL)。

当然,另一种选择是将此动态字符串添加到文件名本身,然后使用重写工具将其删除。无论哪种方式,都做了同样的事情 - 在重写期间定位一串文本并删除它。这允许你欺骗浏览器,但不能欺骗服务器:)


<强>更新

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

  • 检查每个资源
  • 创建一个新文件(或映射到此文件),其名称是其内容的哈希值
  • 向您的网页添加<script> / <link>代码时,会使用散列名称
  • 当请求散列命名文件时,它将提供原始资源
  • 哈希命名文件缓存为“forever”

这个设置有什么好处,你不必担心正确缓存 - 只需将文件设置为永久缓存,并且散列应该根据内容处理可用的文件/映射。它还提供了已经快速缓存和加载回滚/撤消的功能。

答案 1 :(得分:0)

我在这种情况下使用no-cache参数... a有一个字符串常量值,如(来自配置文件)

$no_cache = "v11";

在页面中,我使用像

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

当我更新我的代码时,只需更改$ no_cache值,它就像魅力一样。