按下 F5 后,浏览器前端究竟发生了什么?
当你按下 F5(或点击刷新按钮、输入回车)时,浏览器会启动一次完整的页面重新加载流程。这个过程涉及浏览器、网络、服务器、缓存策略、JavaScript 执行引擎等多个层面。
下面按真实时间线和执行顺序,完整拆解一次典型的 F5 刷新在浏览器前端到底发生了什么(以现代 Chromium 内核浏览器为例,2025–2026 主流行为)。
1. 用户按下 F5 → 浏览器的第一反应(~0–10ms)
浏览器接收到刷新意图
检查当前页面是否处于**“可恢复状态”**(比如正在播放视频、表单有未提交内容)
- 如果有
beforeunload事件监听 → 弹出“确定要离开此页面吗?”确认框 - 用户点击“离开”或没有监听 → 继续
- 如果有
浏览器决定本次刷新的导航类型(Navigation Type):
reload(普通 F5)reload-bypass-cache(Ctrl + F5 / Cmd + Shift + R)history navigation(前进/后退)
2. 决定是否使用缓存(Cache-Control / ETag / Last-Modified 判断)
这是 F5 和 Ctrl+F5 行为差异最大的地方:
| 操作方式 | 浏览器行为 | 是否强制重新请求主文档 | 是否检查子资源缓存 |
|---|---|---|---|
| 普通 F5 | 正常重新加载(revalidate) | 通常 yes(取决于 Cache-Control) | 优先检查缓存(304 可复用) |
| Ctrl + F5 | 强制绕过缓存(force reload) | 强制重新请求(no-cache) | 强制重新请求所有子资源 |
| 地址栏回车 | 类似普通 F5(但部分浏览器更倾向复用缓存) | 同普通 F5 | 同普通 F5 |
主文档(HTML)的缓存决策流程(最关键):
检查
Cache-Control响应头no-cache/no-store→ 必须重新请求max-age=0/ 已过期 → 发起条件请求(带 If-Modified-Since / If-None-Match)- 还在有效期内 → 直接使用缓存(200 from disk/memory cache)
如果需要验证 → 发送带条件头的请求:
If-None-Match: "etag值"If-Modified-Since: 上次修改时间
服务器返回:
- 304 Not Modified → 使用本地缓存
- 200 OK + 新内容 → 使用新内容
3. 浏览器开始真正的加载流程(Navigation Start)
按时间线顺序:
beforeunload事件(如果有)
→ 页面可以弹窗阻止离开(最常见是表单未保存提醒)unload事件(老旧,不推荐依赖)
→ 现代浏览器几乎不保证执行页面被清空(~10–50ms)
- 销毁当前页面所有 DOM
- 终止所有运行中的 JavaScript 执行上下文(除非是 SharedWorker/ServiceWorker)
- 清空绝大多数内存中的 JS 对象(但部分缓存可能保留)
创建新的浏览上下文(Browsing Context)
- 新建一个“空白画布”
- 触发navigation start
发起主资源请求(HTML)
- DNS 解析(若无缓存)
- TCP 三次握手(若无连接复用)
- TLS 握手(HTTPS)
- 发送 HTTP 请求(带 Cookie、Referer、User-Agent 等)
接收到 HTML 响应
- 浏览器开始流式解析(不是等全部下载完再解析)
- 构建DOM Tree(HTML Parser)
- 遇到
<script>、<link>、<img>等 → 发起子资源请求
4. 关键的解析与执行阶段(最容易被忽视的部分)
| 阶段 | 发生什么 | 是否阻塞渲染 | 典型耗时占比 |
|---|---|---|---|
| HTML Parsing | 构建 DOM Tree | — | 中等 |
| CSSOM 构建 | 解析 CSS → 构建 CSSOM | 阻塞渲染(Render-Blocking) | 中等 |
| Preload / Early Hints | 103 Early Hints / link rel=preload | 提前发起关键资源请求 | 优化关键 |
| JavaScript 执行 | 执行同步<script>、async/defer 策略 | 同步阻塞、async 不阻塞 | 波动最大 |
| Pre-parser / Speculative | 浏览器猜测下一个资源提前下载 | — | 现代优化 |
| Style Recalculation | 计算 CSS 规则 → 生成 Computed Style | — | 中等 |
| Layout (Reflow) | 计算每个元素的位置、大小(Layout Tree) | 耗时最长阶段之一 | 高 |
| Paint | 生成图层、栅格化 → 绘制到屏幕 | — | 中等 |
| Composite | 图层合成 → GPU 加速最终画面 | 通常很快 | 低 |
5. F5 刷新时 JavaScript 的几种命运
| 脚本类型 | F5 普通刷新时行为 | Ctrl+F5 时行为 | 是否保留状态 |
|---|---|---|---|
同步<script> | 重新下载 + 重新执行 | 强制重新下载 + 执行 | 丢失 |
<script async> | 可能从缓存执行(取决于 Cache-Control) | 强制重新下载 + 执行 | 丢失 |
<script defer> | 同 async | 同 async | 丢失 |
内联<script> | 直接重新执行(不发请求) | 直接重新执行 | 丢失 |
| Service Worker | 可能继续拦截(除非 unregister) | 可能被更新 | 可能保留 |
| localStorage / IndexedDB | 保留(不随刷新清空) | 保留 | 保留 |
| sessionStorage | 刷新保留,关闭标签页清空 | 刷新保留 | 保留 |
6. 现代浏览器对 F5 的若干优化(2025–2026)
- bfcache(Back/Forward Cache):部分浏览器在后退/前进时使用内存快照,而非重新请求
- 103 Early Hints:服务器提前返回子资源链接,浏览器提前预加载
- HTTP/2 & HTTP/3:连接复用、多路复用、0-RTT 复用
- Cache Partitioning:防止跨站点追踪(Top-level site + frame 的组合 key)
- Speculation Rules:预渲染 / 预取(Chrome 等)
总结:按下 F5 后真正发生了什么(一句话版)
浏览器清空当前页面 → 发起主文档请求(可能带条件头)→ 流式解析 HTML → 并行加载 CSS/JS/图片 → 构建 DOM + CSSOM → 执行 JS → 计算样式 → 布局 → 绘制 → 合成 → 显示新页面。
普通 F5≈ “有条件重新验证 + 复用大部分子资源缓存”
Ctrl + F5≈ “强制重新获取所有资源,相当于第一次访问”
想深入哪个环节?
A. 浏览器缓存策略全解(Cache-Control、ETag、Vary 等)
B. F5 时 JavaScript 重新执行的详细生命周期
C. bfcache 与普通刷新的区别(后退/前进 vs F5)
D. HTTP/3 + Early Hints 如何让 F5 更快
E. Chrome DevTools Network 面板如何看清整个过程
告诉我字母,我们继续深挖!