- 测试
- 性能剖析
- 指标监控
【免费下载链接】sitespeed.io
sitespeed.io is an open-source tool for comprehensive web performance analysis, enabling you to test, monitor, and optimize your website’s speed using real browsers in various environments.
chrome-har 是 sitespeed.io 生态中的独立工具型库:它接收你自行捕获的 Chrome DevTools Protocol(CDP)事件流,输出符合 HAR 1.2 规范的文件。读完本文,你能掌握harFromMessages的完整用法、两个可选参数(磁盘缓存资源、响应体)的含义与默认值、如何为 SPA 软导航拆分 HAR 页面,以及 sitespeed.io 内部是如何消费 chrome-har 产出的 HAR 数据的(存储插件、域名聚合器与真实 HAR 样例结构)。
定位与来历:面向工具开发者的 HAR 生成库
Chrome-HAR 的核心定位是给工具作者使用的库(a library for tool makers):你自己捕获 Chrome DevTools Protocol 的事件,把事件数组交给 Chrome-HAR,即可得到一个 HAR 文件。它最初是从 Browsertime 中抽取出来的——早期实现参考了 Chromedriver_har 的思路,后来 sitespeed.io 团队把这部分能力独立成包,方便其他项目直接复用(见 历史发布说明 中对这次拆分的描述)。
两个对使用者重要的事实:
- 版本形态:自 1.0.0 起 Chrome-HAR 是纯 ESM 包,必须用
import而不是require引入。 - 当前版本:sitespeed.io 仓库文档侧标注的 chrome-har 版本为1.3.1(版本文件),同时 npm-shrinkwrap.json 中锁定的依赖版本也是
chrome-har@1.3.1,说明当前 sitespeed.io(42.7.0)通过 browsertime 28.3.0 间接依赖的正是这个版本。
安装
npm install chrome-har快速开始:把 CDP 消息流转成 HAR
核心 API 只有一个函数:harFromMessages(messages)。messages是你收集到的 CDP 事件数组:
import { harFromMessages } from 'chrome-har'; // `messages` is the array of Chrome DevTools Protocol events you have collected. const har = harFromMessages(messages); // Do whatever you want with the HAR file.返回的har就是完整 HAR 对象,包含log.pages(页面级信息与pageTimings)和log.entries(每个请求的条目)。
可选参数(Options)
harFromMessages(messages, options)接受第二个参数对象,共有两个开关:
| 选项 | 默认值 | 作用 |
|---|---|---|
includeResourcesFromDiskCache | false | 是否把从 Chrome 磁盘缓存中命中的请求也写入 HAR |
includeTextFromResponseBody | false | 是否写入响应体。注意:调用方有责任在把消息传入之前,自行把body挂到 response 对象上(做法见下节) |
import { harFromMessages } from 'chrome-har'; const har = harFromMessages(messages, { includeResourcesFromDiskCache: true, includeTextFromResponseBody: true });响应体:为什么需要拦截请求
响应体并不在标准 CDP 事件Network.responseReceived的 payload 中,因此默认流程拿不到 body。要把它写进 HAR,需要三步:
- 拦截请求,监听
Network.requestIntercepted; - 通过
Network.getResponseBodyForInterception拉取 body,并挂到params.response.body上; - 用
Network.continueInterceptedRequest恢复请求,并把这条消息作为合成的Network.responseReceived事件推入事件数组,最后以includeTextFromResponseBody: true调用harFromMessages。
官方给出的完整示例:
const harEvents = []; client.on('Network.requestIntercepted', async params => { const response = await client.send('Network.getResponseBodyForInterception', { interceptionId: params.interceptionId }); if (params.response != null) { params.response.body = response.body; } else { params.response = response; } await client.send('Network.continueInterceptedRequest', { interceptionId: params.interceptionId }); harEvents.push({ method: 'Network.responseReceived', params }); }); const har = harFromMessages(harEvents, { includeTextFromResponseBody: true });注意示例里对params.response的分支处理:拦截事件里 response 可能已经存在(此时只需补body),也可能为null(此时整体替换为getResponseBodyForInterception的返回),两种情况都覆盖到了。
软导航(Soft Navigation):SPA 路由切换也生成独立 HAR 页面
单页应用的 hash/路由切换不会触发完整文档加载,但 Chrome-HAR 支持把它们捕获为各自独立的 HAR 页面:调用方在 Chrome 的PerformanceObserver报告发生软导航时,主动推一条合成的SoftNavigation.detected消息,并携带新 URL;Chrome-HAR 会据此切换当前页面。如果通过 Browsertime 运行,这一步是自动完成的;单独使用 Chrome-HAR 时你可以自行发出该事件:
messages.push({ method: 'SoftNavigation.detected', params: { url: 'https://example.com/route' } });sitespeed.io 内部如何消费 chrome-har 的产物
在 sitespeed.io 中,chrome-har 并不是直接暴露给终端用户,而是作为浏览器引擎链路的一部分工作:sitespeed.io 的 browsertime 插件 通过BrowsertimeEngine(browsertime 包)驱动真实浏览器,引擎内部使用 chrome-har 把 CDP 事件转成 HAR,再以browsertime.har消息形式进入 sitespeed.io 的消息队列。仓库中可以看到几个佐证点:
- HAR 存储插件:harstorer 插件 监听
browsertime.har消息,把 HAR 序列化为 JSON 写入结果目录;开启--gzipHAR后会把 JSON 流式压缩为.har.gz再落盘(CLI 选项定义中可见该 boolean 选项,默认false)。 - 大文件读取路径:browsertime reader 中专门实现了流式 gunzip,注释明确提到 "Chrome traces and HARs are routinely 50+ MB"——这正是 HAR 作为重型产物在工具链中流转的实证。
- 下游消费者:domains 聚合器 直接从 HAR 条目的
entry.timings(blocked/dns/connect/ssl/send/wait/receive)和response._transferSize(回退到bodySize)计算各域名的请求量、总耗时与传输字节统计,注释中也写明 "Browsertime / chrome-har set_transferSize(compressed) when CDP delivered the value"。
真实 HAR 长什么样:以仓库内置 fixture 为例
test/fixtures/www-thegreenwebfoundation-org.har 就是一份由 chrome-har 生成的真实 HAR,可以快速认识它的结构:
log.creator.name为"chrome-har",log.version为"1.2"(fixture 头部);pages[0]带有非标准扩展字段:_url(被测 URL)、_meta.connectivity(如"native"),以及pageTimings中的_firstPaint、_domInteractiveTime、_domContentLoadedTime等站点速度指标;- 每个 entry 携带 chrome-har 的扩展字段:
_requestId、_initialPriority/_priority(如VeryHigh)、_requestTime、serverIPAddress,timings中除标准七段外还有_queued; - response 中除标准
content.size/content.compression外,还有 chrome-har 特有的bodySize与_transferSize(压缩后的线上字节数)。
从发布记录看,这些扩展字段是持续演进的:chrome-har 0.2.1 补充了serverIPAddress、正确的bodySize与_transferSize等(见 CHANGELOG),而 1.3.0 又为每个 entry 新增了_renderBlocking字段,直接映射 Chrome 108+ 的 CDPrenderBlockingStatus,让下游 HAR 消费者无需再从 trace 推断哪些资源阻塞了首次绘制(见 chrome-har 发布 feed)。
报 Bug 时:如何提供 CDP 事件轨迹
当 HAR 缺少条目或内容异常时,官方要求附上 CDP 事件轨迹以便复现。采集方式是给浏览器引擎打开 perflog 收集:
- 直接用 Browsertime:
browsertime --chrome.collectPerfLog -n 1 https://www.sitespeed.io- 用 sitespeed.io:
sitespeed.io --browsertime.chrome.collectPerfLog -n 1 https://www.sitespeed.io需要附上的文件是chromePerflog-1.json.gz——把它附到 issue 或放到 gist 中共享。这套流程在 Bug 报告文档 的"按 bug 类型采集对应证据"表格中也被列为 Chrome HAR 类问题的标准做法(--chrome.collectPerfLog→chromePerflog-1.json.gz)。
小结与适用前提
- chrome-har 的输入是你自己捕获的 CDP 事件数组,它不负责连接浏览器、发起拦截;拦截响应体(
getResponseBodyForInterception链路)与 SPA 软导航事件的发射,在独立使用时都由调用方完成。 - 默认不含磁盘缓存命中与响应体,两个开关按需开启;开启
includeTextFromResponseBody前必须先按上文方式把body挂到 response 上。 - 在 sitespeed.io 语境下,你通常不直接调用 chrome-har,而是通过
--gzipHAR控制 HAR 落盘形态、通过--browsertime.chrome.collectPerfLog收集排障轨迹,再结合 HAR 存储插件 产出的browsertime.har(.gz)文件分析结果。 - 版本前提:本文描述基于当前仓库(sitespeed.io 42.7.0)对应的 chrome-har 1.3.1 行为,且 1.0.0 起仅支持 ESM 导入方式。
- 测试
- 性能剖析
- 指标监控
【免费下载链接】sitespeed.io
sitespeed.io is an open-source tool for comprehensive web performance analysis, enabling you to test, monitor, and optimize your website’s speed using real browsers in various environments.
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考