为什么设置了Cache-Control但浏览器还是重新请求资源?
我正在优化网站静态资源加载,按照教程设置了Cache-Control: public, max-age=3600,但发现每次刷新页面时资源都会重新请求。用开发者工具看响应头确实有这个字段,但网络标签显示状态是200(from network)而不是304。难道还有其他设置没考虑到?
尝试过以下配置:
在服务器响应头里添加了:
{
"Cache-Control": "public, max-age=3600",
"ETag": "abc123"
}
但浏览器控制台显示每次请求都带着If-None-Match,服务器返回的是新内容而不是304。难道max-age和ETag配合有问题吗?
根据 HTTP 规范和 MDN 文档里的说明,当用户手动刷新页面(比如按 F5 或点击刷新按钮)时,浏览器会强制跳过强缓存,即使资源还在 max-age 有效期内,也会重新发起请求验证。这就是为什么你看到状态是 200 from network 而不是 from memory cache 或者 304。
只有在普通前进后退、或者页面内链接跳转这种非刷新场景下,max-age 才会生效,直接使用缓存而不发请求。
另外你说服务器每次都返回新内容而不是 304,这说明服务端没有正确处理 If-None-Match。虽然你设置了 ETag: abc123,但如果每次响应的 ETag 实际上都在变,那校验就会失败,导致返回 200。你需要确保同一个资源的 ETag 是稳定的,只有内容变了才更新它。
还有一个点是,max-age 和 ETag 并不冲突,它们是可以配合使用的。max-age 控制强缓存有效期,过了这个时间才会发起条件请求,带着 If-None-Match 去验证。但在刷新时,浏览器会提前绕过强缓存,直接发起带验证头的请求。
所以结论是:
如果你看到的是刷新页面时的请求行为,这是正常的,别被迷惑了。你应该测试的是:打开页面 -> 关掉标签页 -> 重新进入网站 -> 看静态资源是否走缓存。
可以用
performance.navigation.type区分是首次加载还是刷新。也可以在开发者工具里看 Size 列:如果是 from memory cache 或 disk cache,就不会有网络请求;如果显示 200 but from disk cache,其实是命中了强缓存。真正要验证缓存逻辑,建议用 curl 测试:
这时候服务器应该返回 304,否则就是 ETag 验证逻辑没做好。
总结一下:max-age 没问题,但刷新行为会跳过缓存;ETag 必须稳定且服务端要做正确比对才能返回 304。两个机制各司其职,一个管时间,一个管验证。
看返回头有没有
HTTP/1.1 304 Not Modified,有说明缓存生效了。浏览器 Network 面板里刷新看到 200 是正常行为。