Cache-Control 设置了 max-age=3600,为什么浏览器还是发请求? 柯言 ☘︎ 提问于 2026-02-25 19:44:18 阅读 29 优化 我给静态资源加了 Cache-Control: max-age=3600,但每次刷新页面,浏览器还是会发请求到服务器,只是返回 304。不是应该直接用本地缓存、不发请求才对吗? 我用的是 Nginx,配置如下: location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1h; add_header Cache-Control "public, max-age=3600"; } 我来解答 赞 6 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 1 条解答 司徒英洁 Lv1 你这个配置其实没问题,但有个常见的误解:max-age=3600 确实会让浏览器在 1 小时内不重新验证,但前提是没有强制刷新(Ctrl + F5)或地址栏回车时带 If-Modified-Since/If-None-Match 头。 你看到的 304,说明浏览器其实发了条件请求(带 If-Modified-Since / If-None-Match),这通常发生在: - 页面第一次加载时,浏览器缓存了资源和 Last-Modified / ETag; - 后续刷新(不是硬刷新)时,浏览器会发一个带验证头的请求; - 服务器发现资源没变,返回 304,告诉浏览器“用本地缓存吧”。 但按理说,如果 Cache-Control 里有 max-age 且没过期,浏览器应该直接走内存/磁盘缓存,连请求都不发才对。 你检查下这个细节:Nginx 的 expires 指令其实会自动加 Cache-Control 的 max-age,但你又手动加了一次,虽然不冲突,但容易混淆。 更重要的是——Nginx 的 expires 默认用的是 Cache-Control: max-age=3600,但如果你没配置 add_header 覆盖,它不会自动加 public,而你加了 public,没问题,但要注意: - 如果你用了 add_header,那 Nginx 就不会再自动加默认的 Expires 和 Cache-Control,这是对的; - 但关键点在于:浏览器是否真的收到了 Cache-Control: public, max-age=3600 这个头? 建议你用浏览器 DevTools 的 Network 标签,点开那个资源,看 Response Headers 里是不是真有这个头。有时候 Nginx 配置没生效(比如 location 匹配不到),或者被 upstream 覆盖了。 还有一个坑:如果你的资源 URL 里有查询参数(比如 /app.js?v=123),而 Nginx 配置里没处理 query string,可能缓存头没生效。不过你用的是正则匹配静态文件后缀,一般没问题。 最后说个更优雅的写法,把 expires 和 add_header 合起来,避免重复: location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1h; add_header Cache-Control "public, max-age=3600, immutable"; } 加个 immutable 可以彻底防止浏览器在刷新时发条件请求(Chrome 87+ 支持),这样连 304 都不会有了,直接本地走缓存——当然,前提是资源 URL 加了 hash(比如 app.a1b2c3.js),否则改了文件用户拿不到最新版。 如果没加 hash,建议别加 immutable,不然更新会很痛苦。 你先看看 Network 里那个资源的响应头是不是真带了 Cache-Control,如果有了还发请求,大概率是浏览器策略(比如你手动刷新了),不是配置问题。 回复 点赞 3 2026-02-25 20:00 加载更多 相关推荐 2 回答 35 浏览 Cache-Control 设置了 max-age=3600,为什么浏览器还是发请求? 我给静态资源加了 Cache-Control: max-age=3600,但每次刷新页面,浏览器还是会向服务器发请求,只是返回 304。不是应该直接用缓存、不发请求才对吗? 我试过在 Nginx 里配... UX玉萱 优化 2026-03-05 10:59:21 2 回答 53 浏览 设置了Cache-Control:max-age=3600后页面还是频繁请求CSS文件? 在开发中,我给CSS文件设置了HTTP头Cache-Control: max-age=3600,但发现每次刷新页面时,浏览器都会重新请求该文件。明明应该缓存一小时才对啊! 尝试过清除浏览器缓存后再访问... UX佳丽 优化 2026-02-11 08:01:10 2 回答 92 浏览 为什么设置了Cache-Control但浏览器还是重新请求资源? 我正在优化网站静态资源加载,按照教程设置了Cache-Control: public, max-age=3600,但发现每次刷新页面时资源都会重新请求。用开发者工具看响应头确实有这个字段,但网络标签显... 晴文 Dev 前端 2026-02-04 10:45:26 2 回答 113 浏览 为什么设置了Cache-Control还是没生效? 我在 Nginx 里给静态资源加了 Cache-Control: max-age=31536000,但每次刷新页面浏览器还是会重新请求图片,状态码是 200 而不是 304 或 from disk c... Des.素伟 前端 2026-03-17 12:03:24 2 回答 60 浏览 为什么设置了Cache-Control还是频繁请求资源? 我在开发单页应用时给API接口设置了Cache-Control:max-age=30,但发现每次页面刷新都会重新请求JSON数据,明明应该缓存30秒才对。 代码是这样写的:fetch('/a... 志青 Dev 优化 2026-02-16 01:01:32 2 回答 48 浏览 为什么设置了Cache-Control还是频繁发起请求? 大家好,我在优化API请求时设置了Cache-Control:max-age=300,但发现页面刷新时还是频繁发起请求,控制台网络标签也没显示缓存命中的状态。比如获取用户信息的接口,明明30秒内重复访... UP主~新杰 优化 2026-02-13 16:04:32 2 回答 59 浏览 设置 Cookie 的 Max-Age 为什么没生效? 我在前端用 JavaScript 设置了一个带 Max-Age 的 Cookie,但发现它好像没起作用,关闭浏览器后 Cookie 还在。我查了文档说 Max-Age 是秒数,应该能控制过期时间,但实... UE丶芸倩 安全 2026-03-14 14:07:20 2 回答 136 浏览 为什么设置了max-age的Persistent Cookie没保存到下次访问? 我在登录接口里设置了带max-age=3600的Cookie,明明设置了持久化时间,但刷新页面后cookie就消失了。测试代码是这样的: res.cookie('token', token, { ma... 轩辕子寨 安全 2026-01-28 00:55:44 1 回答 29 浏览 Cookie 的 Max-Age 设置为 0 真的能立即删除吗? 我在做登录登出功能时,想用设置 Max-Age=0 来清除 Cookie,但发现浏览器里 Cookie 还在,是不是我理解错了? 后端返回的 Set-Cookie 头是这样写的: Set-Cookie... 令狐爱霖 安全 2026-03-17 12:30:25 2 回答 37 浏览 Cache-Control 设置了却没生效? 我给静态资源加了 Cache-Control,但浏览器还是每次都请求,根本没缓存,这是为啥? 我在 Nginx 里配置了 expires 1y;,也试过直接在 HTML 的 meta 标签里写,但刷新... Mr.树遥 优化 2026-02-26 18:12:22
你看到的 304,说明浏览器其实发了条件请求(带 If-Modified-Since / If-None-Match),这通常发生在:
- 页面第一次加载时,浏览器缓存了资源和 Last-Modified / ETag;
- 后续刷新(不是硬刷新)时,浏览器会发一个带验证头的请求;
- 服务器发现资源没变,返回 304,告诉浏览器“用本地缓存吧”。
但按理说,如果 Cache-Control 里有 max-age 且没过期,浏览器应该直接走内存/磁盘缓存,连请求都不发才对。
你检查下这个细节:Nginx 的
expires指令其实会自动加Cache-Control的 max-age,但你又手动加了一次,虽然不冲突,但容易混淆。更重要的是——Nginx 的
expires默认用的是Cache-Control: max-age=3600,但如果你没配置add_header覆盖,它不会自动加 public,而你加了 public,没问题,但要注意:- 如果你用了
add_header,那 Nginx 就不会再自动加默认的Expires和Cache-Control,这是对的;- 但关键点在于:浏览器是否真的收到了
Cache-Control: public, max-age=3600这个头?建议你用浏览器 DevTools 的 Network 标签,点开那个资源,看 Response Headers 里是不是真有这个头。有时候 Nginx 配置没生效(比如 location 匹配不到),或者被 upstream 覆盖了。
还有一个坑:如果你的资源 URL 里有查询参数(比如
/app.js?v=123),而 Nginx 配置里没处理 query string,可能缓存头没生效。不过你用的是正则匹配静态文件后缀,一般没问题。最后说个更优雅的写法,把 expires 和 add_header 合起来,避免重复:
加个
immutable可以彻底防止浏览器在刷新时发条件请求(Chrome 87+ 支持),这样连 304 都不会有了,直接本地走缓存——当然,前提是资源 URL 加了 hash(比如app.a1b2c3.js),否则改了文件用户拿不到最新版。如果没加 hash,建议别加 immutable,不然更新会很痛苦。
你先看看 Network 里那个资源的响应头是不是真带了 Cache-Control,如果有了还发请求,大概率是浏览器策略(比如你手动刷新了),不是配置问题。