直接看Network面板中index.html请求的Size列和Status:显示“from memory cache”或“from disk cache”说明命中强缓存;Status为304说明命中协商缓存;Status为200且Size显示具体字节数说明未命中缓存。

怎么看 HTML 请求是否命中缓存
直接打开浏览器 DevTools → Network 面板,刷新页面后找到 index.html 对应的请求,关键看两处:
-
Size列显示from memory cache或from disk cache:说明浏览器用了本地缓存,没发网络请求 -
Status是304 Not Modified:说明发了条件请求(带If-None-Match或If-Modified-Since),服务端确认没变,复用本地副本 -
Status是200且Size显示具体字节数(如2.4 KB):说明重新下载了,缓存未命中或已过期
注意:强制刷新(Ctrl+Shift+R)会跳过所有缓存逻辑,永远走完整请求,此时看到的不是真实缓存行为。
如何确认 Cache-Control 值来自服务端而非 meta 标签
现代浏览器(Chrome 90+、Firefox 80+、Safari 15+)完全不读取 <meta http-equiv="Cache-Control">。它只认响应头里的值。
验证方法唯一且必须:
立即学习“前端免费学习笔记(深入)”;
- 确保页面通过
http://或https://访问(file://无 HTTP 头,测试无效) - 在 Network 面板中点击
index.html请求 → 查看Headers选项卡 → 展开Response Headers - 如果看到
Cache-Control: public, max-age=300,这个值 100% 来自 Nginx / Apache / CDN / 后端代码(如 Express 的res.set('Cache-Control', ...))
你改了 <meta> 却没变化?不是配置错了,是浏览器压根没解析那行 HTML —— 缓存策略在 HTML 解析前就已锁定。
为什么有时看到 304 却检测不到 HTML 更新
轮询 index.html 检测更新时,如果 Network 面板里全是 304,说明服务端始终返回“未修改”,前端 fetch 根本收不到新内容,自然无法比对脚本路径变化。
根本原因常是:
- 服务端开启了协商缓存(默认行为),但没正确生成或更新
ETag或Last-Modified - CDN 或反向代理(如 Cloudflare、Nginx)缓存了
304响应,导致后续请求连服务端都没触达 - fetch 调用没加
cache: 'no-cache',被浏览器层自动转成条件请求
解决办法:临时让服务端对 /index.html 返回 Cache-Control: no-cache, must-revalidate,并确保 fetch('/index.html', { cache: 'no-cache' }),强制拿到 200 响应体再解析。
检查 ETag 和 Last-Modified 是否生效的关键点
这两个字段本身不控制缓存,只配合 Cache-Control 在协商阶段起作用。它们是否有效,取决于三件事:
-
Last-Modified必须是标准 GMT 格式,例如Wed, 21 Oct 2024 07:28:00 GMT;用new Date().toUTCString()生成,别用.toISOString() -
ETag必须随资源内容变化而变化,不能是固定字符串或时间戳;推荐用文件内容哈希(如crypto.createHash('md5').update(file).digest('hex')) - 服务端必须实际校验请求头:
If-None-Match对应ETag,If-Modified-Since对应Last-Modified,并正确返回304或200
最易忽略的是:即使你设置了 ETag,若 Cache-Control: max-age=3600 还没过期,浏览器根本不会发带 If-None-Match 的请求 —— 强缓存优先级永远高于协商缓存。



















