F5 刷新:缓存协商与浏览器渲染流程
按 F5 刷新页面,并不是把一切推倒重来。它跳过了强缓存,直接向服务器发起验证请求,如果资源没变就返回 304 继续用本地缓存;变了就拉新内容,然后走一遍完整的渲染流水线。Ctrl+F5 更狠,什么缓存都不认;地址栏回车则优先用强缓存,没命中才协商。搞清这三种操作,排查'怎么就更新不生效'这类问题会快得多。

三种导航的缓存行为
| 操作 | 缓存策略 | 请求特征 |
|---|---|---|
| F5 / 刷新按钮 | 跳过强缓存,启用协商缓存 | 带 If-Modified-Since 或 If-None-Match |
| Ctrl+F5 / Shift+F5 | 完全绕过缓存 | 强制添加 Cache-Control: no-cache, Pragma: no-cache |
| 地址栏回车 / 新标签打开 | 优先使用强缓存 | 强缓存有效时无网络请求 |
开发工具开着'Disable cache'时,F5 的行为会变成强制刷新,这点调试时得留意。
强缓存 vs 协商缓存
强缓存是靠 Cache-Control: max-age 或 Expires 告诉浏览器:'这个资源在多久之内别来烦我'。有效期内根本不发请求,直接从内存或磁盘取,速度最快。但也最容易出问题——页面改版了,用户看到的还是旧界面。
协商缓存则通过 ETag/If-None-Match 或 Last-Modified/If-Modified-Since 这两对头部,让浏览器每次用之前都去服务器问一声:'我存的这个还能不能用?'服务器根据资源是否变化返回 304(用本地缓存)或 200(发新内容)。ETag 基于内容指纹,比 Last-Modified 更准确;Last-Modified 只有秒级精度,而且某些集群环境下文件时间可能不一致。但 ETag 需要服务端计算,简单静态资源用 Last-Modified 也够用了。
F5 刷新时发生了什么
主文档:先验证再解析
按下 F5 后,浏览器对 HTML 文档发起 GET 请求,并带上之前存下的 If-None-Match 或 If-Modified-Since 头(如果有的话):
GET /index.html HTTP/1.1
Host: example.com
If-None-Match: "abc123"
If-Modified-Since: Wed, 25 Nov 2025 10:00:00 GMT
服务器看情况:
- 资源没变 →
304 Not Modified,响应体为空,浏览器直接用硬盘里的缓存 HTML。 - 资源变了 →
200 OK,返回新内容,更新ETag、Last-Modified。
注意,即使 304,浏览器也还是会重新解析 HTML——缓存的是原始字节流,不是 DOM 树。所以 F5 后,整个渲染流程都会重新走。
渲染流水线:无论如何都要跑一遍
拿到 HTML 之后,浏览器会依次进行:
- :解析 HTML,生成节点。没标记 或 的 会堵住解析。


