HTML缓存命中率无法被JavaScript直接读取,但可通过Network面板的Status/Size字段、Performance API的transferSize、X-Cache响应头及服务端日志等组合信号精准反推缓存层级与失效原因。

HTML缓存命中率无法用 JavaScript 直接读取,但能通过组合可观测信号精准反推——关键不是“有没有缓存”,而是“哪一层命中了、为什么没命中、是否被绕过”。
看 Network 面板里的 Status 和 Size 字段
这是最直观、无需代码改动的验证方式。打开 Chrome DevTools → Network,刷新页面后重点观察 index.html 和核心静态资源(如 main.a1b2c3.js):
-
Status显示(from cache)或(from disk cache):说明浏览器本地强缓存生效,没发任何网络请求 -
Status是304且TTFB < 5ms:协商缓存命中,服务器只返回响应头,不传 body -
Status是200且Size列显示具体字节数(比如12.4 KB):强缓存和协商缓存都失效,完整下载 HTML - 注意
X-Cache或X-CDN-Cache响应头:如值为HIT,说明 CDN 层也命中了,属于叠加命中
用 Performance API 捕获 transferSize 和 encodedBodySize
window.performance.getEntriesByType("navigation") 返回的导航记录里,这两个字段是判断缓存行为的关键证据:
-
transferSize === 0:大概率命中本地强缓存(注意:部分浏览器在 304 场景下也可能为 0,需结合responseStatus判断) -
encodedBodySize远小于首次加载值,且transferSize很小:说明复用了压缩后的缓存副本 -
fetchStart → responseStart时间差显著缩短(比如从 200ms 缩到 5ms):典型缓存生效表现,尤其适用于自动化监控上报
检查 Cache-Control 和 ETag 配置是否自相矛盾
很多“缓存没生效”问题其实出在服务端配置冲突上,而不是前端代码:
立即学习“前端免费学习笔记(深入)”;
-
Cache-Control: no-cache被误用于 HTML:它不禁止缓存,但强制每次发条件请求,TTFB 升高、请求数翻倍 -
max-age=0或硬编码no-store:等于主动关闭缓存,浏览器连本地存储都不做 - 缺少
ETag或Last-Modified:协商缓存失效后,浏览器只能重新下载整个 HTML,比没缓存还糟 - 构建产物未带哈希(如始终输出
index.html):即使设了immutable,内容一变就导致旧缓存失效,命中率断崖下跌
关联服务端日志与前端 timing 数据
单看前端指标容易误判。比如前端 transferSize === 0,但用户仍感觉卡顿——问题可能不在缓存,而在 JS 执行或渲染阶段。
- 在 Nginx 日志中开启
$upstream_http_cache_status,记录每次 HTML 请求的真实缓存状态(HIT/MISS/EXPIRED) - 把该状态和服务端时间戳,和前端上报的
domContentLoadedEventEnd、loadEventEnd关联分析 - 发现服务端标记
HIT但前端load时间很长:说明瓶颈在客户端,不是缓存没起作用
真正影响命中率的,往往不是缓存开关开没开,而是 HTML 字节流是否稳定、Cache-Control 是否和部署方式匹配、以及有没有在无意中触发强制刷新(比如用户按 Ctrl+F5)——这些细节在压测和灰度阶段最容易被忽略。



















