【问题标题】:Force browser to reload all cache after site update强制浏览器在站点更新后重新加载所有缓存
【发布时间】:2013-04-02 21:31:03
【问题描述】:

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

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

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

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

我不想做的是将元标记放在页面的标题中以强制缓存任何内容...我只想要告诉客户端发生更新并且它应该获取最新的东西一旦更新了一些东西。我想这只是客户端的某种版本控制。

感谢您的宝贵时间!

【问题讨论】:

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


    【解决方案1】:

    处理此问题的正确方法是更改​​资源的 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> 标签添加到您的页面时,会使用散列名称
    • 当请求哈希命名文件时,它服务于原始资源
    • 以哈希命名的文件被“永久”缓存

    此设置的好处在于您不必担心是否正确缓存 - 只需将文件设置为永久缓存,哈希应该会根据内容处理可用的文件/映射。它还提供了已经缓存和快速加载的回滚/撤消功能。

    【讨论】:

    • “向查询字符串添加值不允许缓存”——从我读过的文档来看,该语句是不准确的。 HTTP GET 由浏览器缓存,有或没有查询字符串。见w3schools.com/tags/ref_httpmethods.asp
    • @pmont 请不要在实际的 W3 文档中引用 W3Schools。您的观点无效,请阅读我发布的链接或提供更合法的内容
    • 没必要生我的气。我部署的网络服务器有所有缓存的查询 url。您观察到哪些服务器没有缓存它们?从您的链接:"This specifically means that responses from HTTP/1.0 servers for such URIs SHOULD NOT be taken from a cache." 也许 HTTP/1.1 的变化可以解释不同的行为?
    • @pmont 这可以解释为什么 http1.0 查询有问题w3.org/Protocols/rfc2616/rfc2616-sec14.html
    【解决方案2】:

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

    $no_cache = "v11";
    

    在页面中,我使用类似的资产

    <img src="a.jpg?nc=$no_cache">
    

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

    【讨论】:

    • 但正如您所指出的,这绝不允许缓存资源。你为什么要这个?
    • 如果不更改 no_cache 值,静态文件将被缓存。仅在更改静态内容时才进行更改。
    • 不,这不是真的。根据 HTTP 规范,任何带有查询字符串的东西都不应该被缓存。有些浏览器遵循这一点,有些则没有。所以浏览器总是会发出请求,因为最后有一个查询字符串。服务器可能已经缓存了它,这很好,但它仍然没有在客户端缓存。
    • @Ian 您误解了您提供的网址中的声明,它与 http1.0 服务器有关,而不是与当今大多数服务器的 http1.1 服务器有关。
    猜你喜欢
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 2010-12-15
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 2012-11-04
    相关资源
    最近更新 更多