HAR 瀑布图怎么读:用 timing 拆出首屏阻塞和慢接口

· 约 5 分钟 🌐 HAR 文件分析

HAR(HTTP Archive)是浏览器 Network 面板的录像带。把它读懂,前端慢加载、API 调用失败、首屏卡顿这些问题大多数能在五分钟内定位。

HAR 是什么

一份 W3C 标准的 JSON 文件,结构:

{
  "log": {
    "version": "1.2",
    "creator": { "name": "WebInspector", "version": "537.36" },
    "pages": [{ "id": "page_1", "title": "...", "pageTimings": {} }],
    "entries": [
      {
        "startedDateTime": "2026-05-02T10:00:00.000Z",
        "time": 1234,
        "request": { "method": "GET", "url": "...", "headers": [], ... },
        "response": { "status": 200, "headers": [], "content": {} },
        "timings": {
          "blocked": 50, "dns": 20, "connect": 100, "ssl": 80,
          "send": 5, "wait": 800, "receive": 200
        }
      }
    ]
  }
}

entries[] 里每条对应一次请求。真正的金矿在 timings 字段——它把单次请求拆成 7 段,每段对应一个性能瓶颈类别。

Timing 七段

含义谁的责任
blocked请求被浏览器排队(连接数上限)或被代理阻塞前端架构(连接复用)
dns域名解析DNS / 浏览器缓存
connectTCP 三次握手网络层 / 距离
sslTLS 握手(包含在 connect 内)TLS 配置 / RTT
send把请求字节发出去上行带宽 / 请求体大小
wait等待第一字节回来(TTFB)后端 / CDN
receive下载响应体下行带宽 / 响应体大小

记住一条原则——这七段加起来约等于 time 字段(总耗时)。看哪段占大头就知道瓶颈在哪。

三个最常见的 timing 模式

模式 1:wait 占 80% — 后端慢

[blocked: 5][dns: 0][connect: 0][ssl: 0][send: 1][wait: 950][receive: 44]
                                                  ▰▰▰▰▰▰▰▰▰▰

TTFB 长——服务器收到请求字节后,自己处理慢。前端无能为力,给后端同学,让他用链路追踪(trace_id)查慢在哪段——常见是 SQL 慢查询、外部 API 依赖慢、GC 卡顿、反代排队。

模式 2:receive 占 80% — 资源太大或网络慢

[blocked: 5][dns: 0][connect: 0][ssl: 0][send: 1][wait: 50][receive: 944]
                                                            ▰▰▰▰▰▰▰▰▰▰

字节量大于带宽。先看资源体积——5 MB 的图片在 4G 网络 receive 几秒很正常。优化方向:

  • 图片 → 用 WebP / AVIF,压缩 50-80%
  • JS bundle → 拆 chunk + tree-shaking
  • 字体 → 子集化(用 字体子集化工具
  • 启用 gzip / brotli
  • 上 CDN 让用户就近取

模式 3:blocked 占 80% — 连接排队

[blocked: 800][dns: 0][connect: 0][ssl: 0][send: 1][wait: 50][receive: 99]
 ▰▰▰▰▰▰▰▰

HTTP/1.1 同域名 6 连接上限。看是不是同一时间发了 20+ 请求到同一个域名——前 6 条 blocked 短,后面的请求依次排队,blocked 累加。

修复:

  • 切 HTTP/2 —— 单连接多路复用,无 6 上限
  • 减请求数:合并 sprite、合 JS bundle、懒加载
  • HTTP/1.1 时代用域名分片(cdn1/cdn2/cdn3),HTTP/2 后反而是反模式

瀑布图的视觉读法

把 entries 按 startedDateTime 排序,每条画一条横线(长度 = time),就是瀑布图。关键看时间轴的”墙”——某个时间点之前的请求都完成了,后面的请求才开始——这就是首屏阻塞点。

时间轴 →
0ms     500ms   1000ms  1500ms  2000ms
[document────]
       [css────]                          ← 阻塞渲染
       [main.js────]                      ← 阻塞解析
              [api1────]
              [api2─────]
                    [img1────]
                    [img2────]
                    [img3────]
                                 [api3──]
                                          ↑ 这里出现 FCP

document 加载完后,CSS 和不带 defer/async 的 JS 阻塞 HTML 解析——它们必须先到位浏览器才会画出第一帧。所以瀑布图的时间轴上能直接看到 FCP(First Contentful Paint)的位置:所有 render-blocking 资源完成的那一刻。

找出首屏 critical path

按这条线索读 HAR:

  1. 第一条 document(HTML)——startTime = 0,整页起点
  2. head 里的 CSS——必须全部加载完
  3. head 里的同步 JS(无 defer/async)——也必须全部加载完
  4. 首屏图片——可见区域内的 img、CSS background

这四类资源中最晚结束的那一条 = 首屏可见时间。其它资源(below-the-fold 图片、analytics、统计、第三方 SDK)都可以异步化,不影响首屏。

经典优化案例

慢站点 5 秒首屏,HAR 显示:

  • document 200ms
  • 4 个 render-blocking CSS 各 800ms(串行加载)
  • 1 个 webfont 1500ms(用 font-display: block 默认)
  • 12 个统计 SDK 同时发,前 6 个秒回,后 6 个 blocked 排队 1500ms

问题——render-blocking 串行 + webfont block 默认。

修复

  • 4 个 CSS 合并成 1 个,并把首屏关键样式 <style> 内联到 HTML
  • webfont 加 font-display: swap,先用 fallback 字体显示
  • 12 个统计 SDK 加 async,且尽量晚加载(DOMContentLoaded 后)

修完首屏 5 秒 → 1.5 秒。

HAR 看不到什么

HAR 是请求级粒度,下面这些它看不到:

看不到的用什么看
主线程长任务 / Layout 抖动DevTools Performance 面板
内存泄漏DevTools Memory 面板
Service Worker 内部逻辑Application → Service Workers
WebSocket 帧 / SSE 流DevTools 内置(HAR 只记一次”开”,不记帧)
渲染瓶颈(重绘 / 重排)Performance 面板的 paint / layout 事件
Web Vitals(LCP / CLS / INP)Lighthouse 或 Performance 面板

HAR 是网络层的速览。性能优化深入到 frame 级、render 级、CPU 级,必须切到 Performance 面板。

脱敏分享的注意点

把 HAR 给后端 / 客服 / 三方调试时,记住 HAR 默认包含:

  • Cookie——一份完整的会话凭证,对方拿到能假冒你登录
  • Authorization 头——Bearer token、Basic 认证密码
  • 请求体——POST 表单的密码、订单详情、PII
  • 响应体——可能含未脱敏的用户数据

永远不要直接发原始 HAR。本工具的”脱敏导出”会把上面这些字段替换成 <redacted>,剩下 URL / 状态 / 耗时 / Header 名足以定位问题。

快速排障 checklist

拿到 HAR 后五步走:

  1. ✅ 顶部统计卡看 4xx / 5xx 数 → 不是 0 就先过滤这些请求看错误
  2. ✅ 按耗时降序看前 5 条 → 抓主要瓶颈
  3. ✅ 单击慢请求看 Timing → 拆 wait / receive / blocked,归因到后端 / 资源 / 连接
  4. ✅ 按 startTime 升序看时间轴前 20 条 → 找首屏阻塞资源
  5. ✅ 需要分享时点脱敏导出 → 剥敏感字段后再发

把这五步固化成肌肉记忆,前端故障定位的时间能从一小时压到五分钟。

配套工具

  • PCAP 抓包查看 — HAR 看不到 TLS 握手层,问题深入到那一层切 pcap
  • JSON 工具 — 想用 JSONPath 分析 HAR 内部结构(如 $.log.entries[?(@.time > 1000)]
  • 代码格式化 — HAR 里的 JS / JSON 响应体可以丢进来美化

❓ 常见问题

总耗时 1200ms,wait 占 950ms,怎么排查?

TTFB 长 = 后端慢。先看 URL 是不是后端业务接口——是的话直接给后端同学,让他用链路追踪看慢在哪段(数据库 / 下游 RPC / 反代 / GC)。如果是静态资源(图片 / JS 文件)TTFB 也长 950ms,那不是源站问题——CDN 没命中、回源链路慢、或边缘节点离用户远。前端能做的——加 CDN、开 HTTP/2 多路复用减少排队、本地缓存。前端永远改不了 wait 长,只能靠后端或缓存。

blocked 时间为什么会很长?

主要是连接复用排队。HTTP/1.1 同一个域名 Chrome 限制 6 个并发连接,第 7 个开始就要排队——blocked 时间能飙到几百毫秒。修复路径——(1) 切到 HTTP/2 / HTTP/3:单连接多路复用,没有 6 个上限;(2) 域名分片(H1 时代老办法):把静态资源分到 cdn1/cdn2/cdn3,每个域名独享 6 连接;(3) 减请求数:合并图标到 sprite 或 icon font,懒加载非首屏图片。看 HAR 里 blocked > 50ms 的请求是不是都集中在同一个域名,往往就是这个原因。

receive 占大头,是带宽问题还是后端问题?

receive 是从首字节到末字节下载完成的时间——大文件(图片 / 视频 / JS bundle)天然 receive 长,是字节数 ÷ 带宽。判断方法——(1) 看响应体大小,如果是 5 MB 的图片在 4G 网络下载 8 秒很合理;(2) 同样大小的资源在不同请求里 receive 差异大,那是网络抖动或服务端 chunked 慢吐;(3) wait 短 + receive 长 + 大文件 = 正常;(4) wait 短 + receive 长 + 小文件 = 网络问题或服务端 send 慢。优化方向是压缩(gzip/brotli)、减体积、CDN、HTTP/2 服务器推送(已废弃)改 preload。

怎么找出阻塞首屏的关键请求?

按 Start Time 升序看前 20 条 + 标红 render-blocking 资源。HTML 文档(document)在 head 里同步加载的 CSS 和 JS 都是阻塞渲染的——浏览器解析到 <link rel="stylesheet"> 必须等下载 + 解析完才往下走,看到 <script>(无 defer/async)也要等。瀑布图上看时间轴,首屏 FCP(首次内容绘制)= 这些阻塞资源全部到位的时间。修——CSS 内联首屏关键样式、JS 加 defer/async、用 <link rel="preload"> 提前预热、字体加 font-display: swap

看到一堆 304 / cached 的请求要不要紧?

304 不要紧但能优化——304 表示客户端发了 If-None-Match 或 If-Modified-Since 验证缓存,服务器回"没改"。代价是依然要往返一次,TTFB 仍然几十到几百毫秒。真正的零开销缓存Cache-Control: max-age=N——浏览器在 N 秒内根本不发请求,HAR 里完全看不到这条。如果你的 HAR 满屏 304,说明缓存策略只用了 ETag/Last-Modified,没用强缓存。静态资源(带 hash 的 JS/CSS/图片)应当配 max-age=31536000 + immutable,业务 API 才用协商缓存。

HAR 没显示 HTTP/2 推送 / 预连接,是工具问题吗?

不是,HAR 规范本身不记录这些。HAR 1.2 W3C 草案的字段以"请求-响应"为单位,看不到——HTTP/2 服务器推送(已被 Chrome 117+ 默认禁用)、<link rel="preconnect"> 触发的 DNS / TLS 提前热身、Service Worker 拦截后从缓存返回的请求(这些会显示但 timing 多为 0)。要看这些用 Chrome DevTools 的 Performance 面板(不是 Network),它能展示 main thread + network + paint 的完整时间线。HAR 是请求级粒度,性能优化进阶要看 frame 级。

静态文件 size 显示 0 是怎么回事?

通常是被 Service Worker 拦截 + 从 Cache Storage 返回——网络层根本没发起请求。HAR 里 size 0、timing 也大多 0、状态码 200,类型显示 "(disk cache)" 或 "(memory cache)"。这是好事——意味着 PWA 缓存生效,二次访问近乎瞬开。如果想确认,看 Service Worker 注册情况和 Cache Storage 内容(DevTools → Application → Service Workers / Cache Storage)。HAR 工具看到的是浏览器最终路径,不区分 SW 还是网络。

🌐 打开 HAR 文件分析 拖入 .har 文件→请求列表/状态/耗时/瀑布·过滤搜索·详情查看·脱敏导出·本地解析不上传