Cache-Control 设置了却没生效?

Mr.树遥 阅读 15

我给静态资源加了 Cache-Control,但浏览器还是每次都请求,根本没缓存,这是为啥?

我在 Nginx 里配置了 expires 1y;,也试过直接在 HTML 的 meta 标签里写,但刷新页面时 network 面板里看到的响应头还是没有有效的缓存策略,资源状态一直是 200 而不是 304 或 from memory cache。

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Cache-Control" content="public, max-age=31536000">
</head>
<body>
  <img src="/assets/logo.png" alt="logo">
</body>
</html>

是不是 meta 标签对静态资源根本不起作用?那我该怎么正确设置缓存?

我来解答 赞 2 收藏
二维码
手机扫码查看
2 条解答
瑞娜 Dev
你这问题踩了两个坑,我一个个说。

第一个坑,meta 标签的 http-equiv 只对当前 HTML 文档生效,对你文档里引用的图片、CSS、JS 这些静态资源完全没用。浏览器请求 logo.png 的时候根本不会管 HTML 里写了啥缓存策略,它只认服务器返回的 HTTP 响应头。所以你那个 meta 写了等于白写。

第二个坑,你说 Nginx 配了 expires 1y; 但响应头里没看到,那大概率是 Nginx 配置没生效。检查一下你配的位置对不对,要配在 location 块里,而且改完得 nginx -s reload。

给你一个正确的 Nginx 配置参考:

server {
listen 80;
server_name yourdomain.com;

location /assets/ {
alias /var/www/assets/;
expires 1y;
add_header Cache-Control "public, immutable";
}
}


改完记得 reload,然后用 curl 命令验证一下响应头有没有带上 Cache-Control 和 Expires:

curl -I http://yourdomain.com/assets/logo.png


还有个常见的坑,你如果在 Chrome DevTools 里勾选了 Disable cache,那什么缓存策略都白搭。或者你用的是 Ctrl+F5 强制刷新,浏览器会直接跳过缓存,Network 面板里会显示 200 而不是 from memory cache。

正常访问(地址栏回车或者点链接跳转)才会走缓存,这时候你应该能看到 200 (from memory cache) 或者 200 (from disk cache)。304 是协商缓存,那是另一套逻辑了,你配了强缓存的话根本不会走到 304 那一步。
点赞
2026-03-02 22:14
东方洋博
meta 标签只对 HTML 页面本身生效,对静态资源比如 logo.png 这种完全没用,浏览器压根不会读你页面里的 meta Cache-Control,它只认 HTTP 响应头里的 Cache-Control。

你配 Nginx 的 expires 1y; 但没生效,大概率是配置没生效或者被覆盖了。先确认几点:

第一,你配的 location 是不是匹配到了 /assets/logo.png 这个路径?比如你是不是写了 location /assets/ { expires 1y; },而不是写成 location = /assets/ 这种精确匹配漏掉了。

第二,你加了 expires 后,有没有 reload 或者 restart Nginx?有时候改完配置不 reload 是不会生效的,这个真别跳过。

第三,你请求的资源是不是带了查询参数?比如 logo.png?v=123,这种路径变化会让缓存失效,但缓存头本身还是生效的,只是你可能误以为没缓存。

第四,最坑的一点:如果你在浏览器里强制刷新(Ctrl+Shift+R 或 Cmd+Shift+R),所有缓存都会跳过,这时候肯定 200,不是你的配置问题。

验证方法:用 curl -I https://your-domain.com/assets/logo.png 看响应头,有没有 Cache-Control 和 Expires 字段。如果 curl 都没,那 Nginx 配置铁定没生效;如果 curl 有,但浏览器没缓存,那就是浏览器缓存被绕过了或者有其他 header 冲突(比如 Set-Cookie、Authorization 会让某些资源无法被缓存)。

正确姿势是 Nginx 里这么配:

location /assets/ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}


注意别用 add_header 覆盖掉 expires,expires 本身就会加 Cache-Control,但如果用了 add_header,要确保别重复或覆盖。immutable 是 Chrome 76+ 支持的,表示文件不会变,连重新验证都不用发,对版本化静态资源特别有用。

最后提醒:别用 meta 标签缓存静态资源,那玩意是给 HTML 页面自己用的,静态资源必须靠 HTTP 响应头,这是后端处理的活儿。
点赞
2026-02-26 18:13