为啥 Chrome 会使用 max-age 标头请求已缓存的图像?
Posted
技术标签:
【中文标题】为啥 Chrome 会使用 max-age 标头请求已缓存的图像?【英文标题】:Why does Chrome make a request for already cached image with max-age header?为什么 Chrome 会使用 max-age 标头请求已缓存的图像? 【发布时间】:2020-08-28 12:28:53 【问题描述】:我的目标是在浏览器的缓存中缓存图片。
当前设置
Cache-Control: public, max-age=10368000
标头附加到请求的图像以缓存图像。
此外,还附加了ETag: f5f9f1fb39790a06c5b93735ac6e2397
标头,以检查到达max-age
后图像是否已更改。
当再次请求相同的图像时,检查if-none-match
标头的值以查看图像是否已更改。如果没有,则返回304
。
我正在使用 Fiddler 来检查 http 流量(注意 - 下面描述的行为在 Fiddler 之前已经发生,所以这不是问题)
Chrome 版本 - 77.0.3865.90(官方版本)(64 位)
预期行为
我预计图像将被缓存 10368000 秒。除非经过 10368000 秒,否则每次请求都会从浏览器的缓存中提供图像。一旦 10368000 秒过去了,就会向检查 Etag 的服务器发出请求。如果图片在服务端没有变化,返回304给客户端,将缓存时间再延长10368000秒。
使用谷歌浏览器的行为
-
第一次请求图像。以下是请求标头
-
图像成功返回,状态为 200。以下是响应标头
Fiddler 告诉我们请求并提供了一张图片
此外,图像被缓存的事实可以在~/Library/Caches/Google/Chrome
中看到。
-
我单击浏览器中的链接栏并按 Enter 再次请求图像。以下是请求标头
-
图像返回成功,状态为 304。以下是响应标头
Fiddler 告诉我们图片是从缓存中提供的
为什么 Chrome 只在收到 304 响应后才对图像提出额外请求并从缓存中提供它?
我看到第二次请求图像时设置了Cache-Control: max-age=0
请求标头。据我了解,这意味着 Chrome 希望在提供缓存图像之前重新验证缓存图像是否有效。但为什么呢?
网上有人说Etag
标头是 Chrome 确保图像有效的原因。即使我不包含Etag
标头,仅在第一个响应中包含Cache-Control: public, max-age=10368000
,Cache-Control: max-age=0
也存在于第二个请求的标头中。
我也尝试过排除公共,将其设为私有等。我还添加了 Expires
和 Last-Modified
对,带和不带 max-age=10368000
并获得相同的行为。
此外,在开发工具中,我没有选中禁用缓存。所以缓存是启用的,这也是有意义的,因为图像是在返回 304 之后提供的。
当我没有单击链接栏并按 Enter 键,而是按刷新箭头(即 CMD + R)时,也会发生这种确切的行为。如果我硬刷新 CMD + SHIFT + R,则请求图像就像是第一次一样请求它,这是有道理的。
使用 Firefox 的行为
Firefox 完全按预期工作。
-
第一次请求图像。以下是请求标头
-
图像成功返回,状态为 200。以下是响应标头
Fiddler 告诉我们请求并提供了一张图片
此外,如果我将鼠标悬停在响应状态上,则显示 OK
-
我单击浏览器中的链接栏并按 Enter 再次请求图像。以下是请求标头
-
图像成功返回,状态为 200。以下是响应标头
但 Firefox 显示它已被缓存。
此外,Fiddler 在第二个请求中未检测到任何活动,因此图像是从 Firefox 的缓存中提供的。与 Chrome 不同,Chrome 向服务器发出另一个请求只是为了从它接收 304。
非常感谢您的宝贵时间和帮助。我非常感谢它,并愿意提供任何其他信息。真的很期待你对此的看法。
祝你有美好的一天:)
【问题讨论】:
【参考方案1】:为什么 Chrome 在收到 304 响应后才对图像发出额外请求并从缓存中提供它?
因为你告诉它——不管你是否意识到!当您向前和向后浏览时,将使用缓存的图像。当您单击刷新或 F5(MacOS 上的 Cmd R)或页面时,您明确要求 Chrome 仔细检查该页面是否仍然正确。因此,当您单击 URL 栏并单击 Enter 时,它是相同的。 Chrome 认为您这样做的唯一原因是,在您已经访问的 URL 上,您必须希望它进行检查。
我看到第二次请求图像时设置了 Cache-Control: max-age=0 请求标头。据我了解,这意味着 Chrome 希望在提供缓存图像之前重新验证缓存图像是否有效。但为什么呢?
正确。 See the answer to this question。至于为什么 - 因为如上所述,您有 Chrome 想要刷新的信号。
还有cache-control immutable header,它旨在告诉浏览器永远不要在缓存中重新获取 - 即使在刷新时也是如此。
Firefox 完全按预期工作。
有趣。我其实很喜欢 Chrome 这样做的方式。当然是重新加载(F5/Cmd + R)。感谢它让您感到困惑(尽管现在您理解它希望不会那么混乱),但测试这不是常态,大多数人不会单击 URL 栏然后在不更改 URL 的情况下按 Enter 键,除非他们想重新检查当前与服务器的页面。
【讨论】:
你确实是对的。我复制了 URL 并将其输入到 Chrome 的新选项卡中,Fiddler 没有捕获任何 http 流量,这意味着内容是从 Chrome 的缓存中提供的。非常感谢巴里。以上是关于为啥 Chrome 会使用 max-age 标头请求已缓存的图像?的主要内容,如果未能解决你的问题,请参考以下文章
Google Chrome忽略Cache-Control标头的原因
http 304 响应与缓存控制相结合似乎不适用于 max-age