Cache-Control 设置了 max-age=3600,为什么浏览器还是发请求? 柯言 ☘︎ 提问于 2026-02-25 19:44:18 阅读 15 优化 我给静态资源加了 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"; } 我来解答 赞 2 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 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,如果有了还发请求,大概率是浏览器策略(比如你手动刷新了),不是配置问题。 回复 点赞 2 2026-02-25 20:00 加载更多 相关推荐 1 回答 25 浏览 设置了Cache-Control:max-age=3600后页面还是频繁请求CSS文件? 在开发中,我给CSS文件设置了HTTP头Cache-Control: max-age=3600,但发现每次刷新页面时,浏览器都会重新请求该文件。明明应该缓存一小时才对啊! 尝试过清除浏览器缓存后再访问... UX佳丽 优化 2026-02-11 08:01:10 2 回答 69 浏览 为什么设置了Cache-Control但浏览器还是重新请求资源? 我正在优化网站静态资源加载,按照教程设置了Cache-Control: public, max-age=3600,但发现每次刷新页面时资源都会重新请求。用开发者工具看响应头确实有这个字段,但网络标签显... 晴文 Dev 前端 2026-02-04 10:45:26 1 回答 35 浏览 为什么设置了Cache-Control还是频繁请求资源? 我在开发单页应用时给API接口设置了Cache-Control:max-age=30,但发现每次页面刷新都会重新请求JSON数据,明明应该缓存30秒才对。 代码是这样写的:fetch('/a... 志青 Dev 优化 2026-02-16 01:01:32 1 回答 30 浏览 为什么设置了Cache-Control还是频繁发起请求? 大家好,我在优化API请求时设置了Cache-Control:max-age=300,但发现页面刷新时还是频繁发起请求,控制台网络标签也没显示缓存命中的状态。比如获取用户信息的接口,明明30秒内重复访... UP主~新杰 优化 2026-02-13 16:04:32 2 回答 100 浏览 为什么设置了max-age的Persistent Cookie没保存到下次访问? 我在登录接口里设置了带max-age=3600的Cookie,明明设置了持久化时间,但刷新页面后cookie就消失了。测试代码是这样的: res.cookie('token', token, { ma... 轩辕子寨 安全 2026-01-28 00:55:44 2 回答 15 浏览 Cache-Control 设置了却没生效? 我给静态资源加了 Cache-Control,但浏览器还是每次都请求,根本没缓存,这是为啥? 我在 Nginx 里配置了 expires 1y;,也试过直接在 HTML 的 meta 标签里写,但刷新... Mr.树遥 优化 2026-02-26 18:12:22 2 回答 38 浏览 设置了Cache-Control后移动端图片还是重复请求是怎么回事? 我在开发移动端混合应用时遇到个奇怪的问题。给图片资源设置了响应头Cache-Control: public, max-age=3600,但用Chrome开发者工具模拟移动端时,发现每次打开页面都会重新... 萌新.柚溪 移动 2026-01-27 23:58:25 2 回答 52 浏览 Vue请求缓存导致数据更新不及时怎么办? 最近在做Vue项目时遇到个奇怪的问题,我给接口设置了Cache-Control: max-age=300,但页面刷新时数据总比实际延迟很久。比如商品价格修改后,用户需要等很久才能看到新价格。 我试过手... 司空子格 优化 2026-02-18 10:39:39 2 回答 160 浏览 Remax中使用Page组件时小程序正常但Web端显示空白页面怎么办? 我在用Remax开发多端应用时遇到奇怪问题,同样的Page组件在小程序端能正常渲染内容,但Web端只显示空白页面。检查过网络请求都没问题,控制台也没有报错。 尝试把页面代码简化到只剩最基础的结构还是不... 设计师卜楷 移动 2026-02-06 21:49:29 2 回答 42 浏览 CORS Origin检查时,为什么设置了Access-Control-Allow-Origin却还是被拦截? 我前端项目在调用后端API时遇到了CORS问题,明明在服务器响应头里设置了Access-Control-Allow-Origin: *,但Chrome还是报错"Origin http://localh... 闲人东正 安全 2026-02-15 11:17:35
你看到的 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,如果有了还发请求,大概率是浏览器策略(比如你手动刷新了),不是配置问题。