【问题标题】:Which are the optimum cache-related HTTP headers for a content that can change?对于可以更改的内容,哪些是与缓存相关的最佳 HTTP 标头?
【发布时间】:2012-07-29 02:16:27
【问题描述】:

我们有几个文件通过 HTTP 提供,并且不时更改。

哪些是与缓存相关的 HTTP 标头,我们应该在 HTTP 响应中返回以优化浏览器加载速度,同时强制浏览器验证它是否具有文件的最新版本?

我们已经设置了一个带有过去日期的“Expires”标头(此时似乎达成了共识)。

但后来有人建议设置这个标题:

Cache-Control: no-cache, no-store, must-revalidate

但是这个标头的问题是它阻止浏览器保留文件的本地副本,所以每次下载文件,即使它没有改变,响应码为 200。

如果我只是使用:

Cache-Control: no-cache

然后浏览器(至少Firefox 14和Chrome 20)保留本地副本,发送If-Modified-SinceIf-None-Match标头,服务器返回304码,文件内容没有下载。 这是这些文件可以随时更改的最佳行为。

问题是我不知道仅仅设置“无缓存”是否足以强制所有浏览器(包括旧但仍在使用的版本)和代理服务器重新验证其本地缓存副本与服务器。

最后,Pragma: no-cache 标头呢?它也应该包含在 HTTP 响应中吗?

【问题讨论】:

  • 如果您有答案,您应该写下自己的答案并将其标记为答案,而不是在您的问题中添加粗体陈述。
  • @AlexisWilke 粗体声明不是我问题的答案,只是我想强调的。

标签: http caching cache-control http-caching no-cache


【解决方案1】:

我找到了两种强制客户端重新检查缓存的方法:

Cache-Control: max-age=0, must-revalidate
Expires: Thu, 01 Jan 1970 00:00:00 GMT

这至少适用于 Firefox。我想 IE 和 Chrome 也会做出正确的反应。它应该适用于使用 HTTP/1.0 的旧版浏览器。

在 HTTP 1.1 中,您可以使用 ETag。在这种情况下,must-revalidate 选项不是必需的,因为拥有ETag 足以让客户端做出反应,就好像must-revalidate 在那里一样:

Cache-Control: max-age=0
ETag: 123
Expires: Thu, 01 Jan 1970 00:00:00 GMT

这将告诉客户端使用ETag 123 创建数据的缓存版本,并在每次需要该数据的副本时重新检查服务器。然后您可以回复304 Not Modified

绝对不能使用的两个选项是:no-cacheno-store

如果您想防止中间缓存缓存数据,请确保将private 添加到Cache-Control 选项中。

作为一个有趣的功能,您还可以使用一个小的 max-age,例如几分钟,让客户端缓存该时间的数据,然后发送一个 GET,您可以用它来回答304:

Cache-Control: max-age=300
ETag: 123
Expires: Tue, 29 Mar 2015 15:05:00 GMT

在这种情况下,浏览器预计 5 分钟内不会检查新数据。之后,它会向您发送If-None-Match: 123

【讨论】:

    【解决方案2】:

    最好的方法是:

    Cache-Control:max-age=315360000, public
    Expires:Tue, 23 Aug 2022 10:53:13 GMT
    

    并给文件一个“内容依赖文件名”,例如 stylesheet_v32.css。 一旦内容发生变化,更改文件名+引用,浏览器就会获得最新版本。如果文件名保留,则浏览器不需要请求它。

    这在所有浏览器中都是安全且一致的。

    依赖Cache-Control: no-cache 和浏览器保存它是我不想做的。

    【讨论】:

      【解决方案3】:

      Google 开发者文档有一个 nice documentation on caching 并提供了一些很好的使用模式。

      例如,它有一个定义最佳缓存控制策略的流程图。

      此外,它还定义了一个很好的模式来为文件添加指纹并设置更长的期限,例如一年。

      • 在资源“过期”之前使用本地缓存的响应
      • 在 URL 中嵌入文件内容指纹使我们能够强制客户端更新到新版本的响应
      • 每个应用程序都需要定义自己的缓存层次结构以获得最佳性能

      定义每个资源缓存策略的能力使我们能够 定义“缓存层次结构”,让我们不仅可以控制多长时间 每个都被缓存,而且新版本被看到的速度有多快 游客。比如,我们来分析一下上面的例子:

      • HTML 标记为“no-cache”,这意味着浏览器将始终在每次请求时重新验证文档并获取 如果内容发生变化,则为最新版本。此外,在 HTML 标记中 我们在 CSS 和 JavaScript 资产的 URL 中嵌入指纹:如果 这些文件的内容会发生变化,而不是页面的 HTML 更改以及 HTML 响应的新副本将是 已下载。
      • CSS 允许被浏览器和中间缓存(例如 CDN)缓存,并设置为 1 年到期。请注意,我们可以使用
        因为我们嵌入了文件,所以 1 年的“遥远的未来到期”安全
        指纹其文件名:如果 CSS 更新,URL 将改变
        也一样。
      • JavaScript 也设置为 1 年后到期,但被标记为私有,可能是因为它包含一些私有用户数据,而
        CDN 不应缓存。
      • 缓存的图像没有版本或唯一指纹,并设置为 1 天后过期。

      ETag、Cache-Control 和唯一 URL 的组合使我们能够 提供世界上最好的:长寿命的到期时间,控制 可以缓存响应,并按需更新

      【讨论】:

      • another documentation from Google 这是矛盾的。在本文档中,他们建议使用 Cache-Control: public, max-age=0, must-revalidate 而不是 Cache-Control: no-cache 来获取可以随时更改的内容。
      • 请注意,ETag 可能会在 Firefox 中导致“问题”,因为它似乎一直在重新检查数据,即使您的缓存持续时间大于零。因此,受版本控制的文件,例如 CSS 和 JS 文件,不应使用ETag
      猜你喜欢
      • 1970-01-01
      • 2012-10-31
      • 1970-01-01
      • 2011-12-03
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 2012-08-06
      • 2011-01-26
      相关资源
      最近更新 更多