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

Mic*_*ack 9 javascript deployment web-applications cache-control glassfish-3

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

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

描述我希望可行的行为:

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

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

谢谢你的时间!

Ian*_*Ian 12

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

/resources/js/fileName.js
Run Code Online (Sandbox Code Playgroud)

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

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

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

/resources/1234/js/fileName.js
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用项目的版本号(或者您希望重新加载缓存文件时手动更改的属性/配置文件中的某些值),因为此编号仅在修改项目时更改.所以你的网址可能如下所示:

/resources/cacheholder${project.version}/js/fileName.js
Run Code Online (Sandbox Code Playgroud)

这应该很容易.

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

/resources/cacheholder______/whatever
Run Code Online (Sandbox Code Playgroud)

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

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


更新:

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

  • 检查每个资源
  • 创建一个新文件(或映射到此文件),其名称是其内容的哈希值
  • 向页面添加<script>/ <link>标记时,将使用散列名称
  • 当请求散列命名文件时,它将提供原始资源
  • 散列命名文件被"永久"缓存

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

  • @pmont这可以解释为什么http1.0查询有问题https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html (2认同)