【问题标题】:Chrome ignores the ETag header and just uses the in memory cache/disk cacheChrome 会忽略 ETag 标头,只使用内存缓存/磁盘缓存
【发布时间】:2017-09-25 08:46:03
【问题描述】:

如果我理解正确,使用 ETags 的流程如下所述:

  • 浏览器将请求发送到服务器。服务器发回带有 ETag 的图像
  • 浏览器将资源与 ETag 一起保存
  • 在下一个请求中,浏览器会发送带有包含已保存 ETag 的标头 If-None-Match 的请求。

当返回响应时,chrome 开发工具告诉我这些是我的标题

Cache-Control:max-age=7200
Connection:keep-alive
Content-Type:image/png
Date:Thu, 27 Apr 2017 13:42:57 GMT
ETag:"b36f59c868d4678033d318a182658e18371df8f5"
Expires:Thu, 27 Apr 2017 15:42:57 GMT
Server:nginx
Transfer-Encoding:chunked
X-Debug-Token:873c8f
X-Debug-Token-Link:http://localhost:8081/_profiler/873c8f

现在,当我重新加载页面时,并没有收集到新图像。它通过 Chrome 的内存缓存或磁盘缓存保存,您可以在此处看到

但是为什么会这样呢?我发送了一个 ETag,为什么浏览器不向服务器发出另一个请求,而是使用它自己的缓存?

我问的原因是,我们想要缓存我们的图像,但是一旦它们发生变化,就应该立即更新它们。为什么 Chrome 会这样做?

更新
我只是注意到它在 Firefox 上可以正常工作,所以这似乎是 chrome 的“功能”,而不是配置功能。

更新 2
在为这样的图像设置我的新标题后

Cache-Control:max-age=0, private
Connection:keep-alive
Content-Type:image/png
Date:Thu, 27 Apr 2017 14:44:57 GMT
ETag:"e5b18bdebe44ed4bba3acb6584d9e6a81692ee27"
Expires:Fri, 27 Oct 2017 14:44:57 GMT
Server:nginx
Transfer-Encoding:chunked
X-Debug-Token:3447a6
X-Debug-Token-Link:http://localhost:8081/_profiler/3447a6

Chrome 仍然使用磁盘缓存来加载数据。这是我现在的 nginx

location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
  access_log off;
  add_header Cache-Control "max-age: 0, must-revalidate";
}

更新 3
我只是做了一些进一步的研究。一旦设置了 Expires 标签,Chrome 就会使用内存或磁盘缓存。与max-age 相同。我不明白,即使设置了must-revalidate,只要设置了Expiresmax-age=>0,Chrome 就不会重新加载资源。

【问题讨论】:

    标签: google-chrome http nginx server


    【解决方案1】:

    服务器告诉 chrome,该资源在接下来的 2 小时(7200 秒)内有效。想必你的第二个请求比那更早。

    max-age: 0max-age: 0, must-revalidate 会更好地为您服务。然后,虽然您永远不会获得完全缓存的操作(甚至不需要访问服务器),但您仍然可以让服务器发送 304 Not Modified 响应以告诉浏览器它可以使用缓存的实体(并根据标头(如果适用))所以当你仍然有一个请求-响应发生时,只会发送大约 300 字节,而不是实体是多少千字节或更多。

    【讨论】:

    • 这就是我们目前正在做的事情。请求到达服务器,我们检查 ETag。如果相同,我们返回304 响应。问题是,它按预期工作。在 Firefox 中,更新图像后,新图像会立即加载。但不是铬。所以我不确定,你认为这是配置错误而不是 Chrome 错误吗?
    • 第二个注意事项:我只是在图像缓存后检查了 CHrome 的请求标头。那里没有设置 If-None-Match 标头。 Firefox 发送此标头,这就是它可能工作的原因。
    • 第五注...:对不起,伙计^^。 Chrome 仍然不会重新加载页面,仍然使用磁盘缓存。
    • @Musterknabe 我遇到了同样的问题,Chrome 没有像 Firefox 那样发送 If-None-Match。你能找出原因吗?
    • @manni 不,这似乎就是 Chrome 的行为方式。 IMO 他们违反了性能标准。虽然不同意他们的观点
    【解决方案2】:

    这是一个旧帖子,但这是我们解决它的方法。

    @Musterknabe 评论你的更新 3:

    同样的事情发生在我们身上,即使在设置之后 must-revalidate chrome 没有重新加载新资源。我发现由于资源已经存在于客户端/浏览器缓存内存中,因此它们是从内存缓存中提供的,并且新请求(获取静态资源)没有触发。所以响应头没有更新为must-revalidate

    为了解决这个问题,我们使用了两个步骤:
    1. 更改资源文件名 - 确保新请求将被触发
    2. 添加缓存控制头到静态文件(在startup.cs) - 照顾未来的静态资源文件的变化。这样以后我们就不必更改资源文件名了。

        public void Configure(IApplicationBuilder app)
        {
            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = ctx =>
                {
                    const int durationInSeconds = 0;
                    ctx.Context.Response.Headers[HeaderNames.CacheControl] =
                        "must-revalidate,max-age=" + durationInSeconds;
                }
            });
        }
    

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      对于可能登陆这里的任何其他人,请注意,如果存在 任何 SSL 错误,Chrome 不会缓存任何内容(例如,如果您使用的是自签名证书)。

      提示我的原始帖子:https://stackoverflow.com/a/55101722/9536265

      Chrome 错误:https://bugs.chromium.org/p/chromium/issues/detail?id=110649(看来他们永远不会修复它,这似乎很荒谬,因为几乎所有开发人员都会在这种情况下进行开发)

      我无法通过文档确认,但 Edge Chromium 的行为似乎相同。另一方面,Firefox 很乐意为使用“不安全”证书的站点遵循标准缓存实践,例如站点名称不完全匹配或自签名证书的站点。我还没有测试过 Safari。

      【讨论】:

        【解决方案4】:

        对于要使用的 ETag 和浏览器发送 If-Modified-SinceIf-None-Match 标头,缓存控制必须设置为 no-cache

        服务器使用Cache-Control: no-cache header 或浏览器使用Request.cache = 'no-cache' option


        在此处阅读有关缓存选项的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Request/cache

        【讨论】:

          猜你喜欢
          • 2017-11-19
          • 2015-10-28
          • 2016-06-12
          • 2022-12-20
          • 2015-10-01
          • 1970-01-01
          • 2018-01-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多