直接查看X-Cache-Status和Cache-Control响应头最可靠:X-Cache-Status为HIT表示CDN或代理缓存命中,MISS说明回源;Cache-Control含max-age等有效值才启用浏览器缓存,no-cache或no-store则禁用缓存。

直接看 x-cache-status 和 Cache-Control 响应头,比刷页面猜效果靠谱得多。 浏览器是否真用了缓存、CDN有没有命中、服务端规则有没有生效——这些不能靠“我刷新了三遍”来判断,得靠网络请求里的真实字段说话。
怎么用 DevTools 看清缓存是否真正生效
打开页面前先清掉本地干扰:按 Ctrl+F5 强制刷新,或开无痕窗口。然后按 F12 → 切到「网络」标签 → 刷新页面。重点盯两个字段:
-
x-cache-status(CDN 或反向代理返回):值为HIT才算从边缘节点取的;MISS表示回源了,哪怕页面看起来“加载快”,也不代表缓存起效 -
Cache-Control(服务端返回):检查是否含max-age=3600这类有效指令;若看到no-cache或no-store,浏览器根本不会存,后续所有“刷新没更新”问题都白调 - 注意:有些 CDN(如将盾)会把
x-cache-status放在响应头里,但 Nginx 默认不带,得手动加add_header X-Cache-Status $upstream_cache_status;
为什么改了 HTML 但用户还是看到旧内容
这不是 CDN 或服务器的问题,大概率是浏览器强缓存锁死了资源。典型表现是:你本地改完、自己用无痕窗口验证通过,客户却还在看昨天的 banner。原因有三:
- 服务端返回了
Cache-Control: public, max-age=86400,但 HTML 文件本身没做版本控制(比如没加 hash 后缀),浏览器就一直用本地副本 - 前端构建没配
html-webpack-plugin的cache: false或 Vite 的build.rollupOptions.output.entryFileNames,导致 index.html 被缓存太久 - 用户访问时触发了启发式缓存(Heuristic Caching):服务端没给
Cache-Control,浏览器按文件最后修改时间自己估算一个过期时间,这个行为不可控且各浏览器不一致
怎么让 HTML 不被缓存,但 JS/CSS 又能缓存
关键在服务端配置的粒度。HTML 是动态入口,必须禁用强缓存;而静态资源可长期缓存,靠文件名哈希区分版本。Nginx 示例配置如下:
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
location ~ \.(js|css|png|jpg|gif|webp|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
注意:immutable 是个重要信号,告诉浏览器“这文件名带 hash,内容绝不会变”,可跳过协商缓存(If-None-Match)直接复用本地副本。没有它,哪怕加了 max-age,浏览器仍可能发一次 304 请求。
curl 命令快速验证缓存头是否下发成功
不用开浏览器,一行命令就能确认服务端是否真的吐出了你要的缓存头:
curl -I https://www.1k4.cn/index.html
看输出里有没有 Cache-Control、ETag、Last-Modified。如果连 Cache-Control 都没有,说明配置没生效或被上层(CDN、WAF)覆盖了。再试加 -H "Cache-Control: max-age=0" 模拟浏览器强制验证请求,观察是否返回 304 —— 这才是协商缓存真正工作的证据。
最容易被忽略的是:CDN 缓存和浏览器缓存是两套独立机制,x-cache-status: HIT 只说明 CDN 节点有副本,不代表浏览器也用了它;而 Cache-Control 失效,哪怕 CDN 再快,用户下次访问照样可能看到旧 HTML。


















