页面刷新耗时不能直接监测“刷新动作本身”,但可通过PerformanceObserver监听navigation类型条目获取端到端耗时,需在<head>同步注册并结合paint类型补全FCP,区分软/硬刷新并轻量上报。

页面刷新耗时不能直接用 PerformanceObserver 监测“刷新动作本身”,因为刷新(location.reload() 或用户手动 F5)会清空当前页面上下文,所有 JS 执行环境、PerformanceEntry 缓存、未上报数据都会丢失。但你可以精准测量两次刷新之间的关键性能指标变化,尤其是导航发起后到新页面可交互/可视的完整耗时——这正是 navigation 类型条目所记录的核心路径。
监听 navigation 类型获取刷新全过程耗时
navigation 条目完整覆盖从用户触发刷新(或跳转)开始,到新页面加载、解析、渲染完成的端到端时间,包含重定向、DNS、TCP、SSL、请求响应、DOM 解析、资源加载等各阶段细分。
- 必须在
<head>最早位置同步注册 observer,否则会漏掉 navigation 数据(该事件在 HTML 解析初期就已生成) - 使用
entryTypes: ['navigation'],回调中取第一个条目(通常即本次导航) - 关键字段:
-
entry.loadEventEnd:load事件完成时间(毫秒,相对 navigationStart) -
entry.domContentLoadedEventEnd:DOMContentLoaded触发完成时间 -
entry.firstPaint/entry.firstContentfulPaint:若浏览器支持且已计算,会直接附在 navigation 条目上(注意:不是所有浏览器都填充)
-
示例代码(需放在 <head> 内联脚本中):
<script>
if ('PerformanceObserver' in window &&
PerformanceObserver.supportedEntryTypes?.includes('navigation')) {
new PerformanceObserver((list) => {
const entry = list.getEntries()[0];
if (entry) {
console.log('刷新总耗时(load结束):', entry.loadEventEnd, 'ms');
console.log('白屏时间(FCP):', entry.firstContentfulPaint || '未支持', 'ms');
console.log('首屏可交互时间(DCL):', entry.domContentLoadedEventEnd, 'ms');
// 可上报给监控系统
sendMetric('refresh_load_time', entry.loadEventEnd);
}
}).observe({ entryTypes: ['navigation'] });
}
</script>结合 paint 类型补全首帧可视化时间
navigation 条目中的 firstContentfulPaint 字段在部分浏览器中可能为空或不准确。为确保捕获真实首帧绘制时间,应同时监听 paint 类型:
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 注册第二个 observer,
entryTypes: ['paint'] - 在回调中过滤
entry.name === 'first-contentful-paint' - 用
entry.startTime作为最终确认的首帧时间(单位毫秒,同样相对 navigationStart)
注意:两个 observer 都必须在 <head> 同步执行,不可 defer、async,也不可等到 DOMContentLoaded 再初始化。
区分“软刷新”与“硬刷新”的影响
用户行为不同,刷新路径差异大:
- 点击按钮调用
location.reload()是软刷新,通常复用部分缓存资源 - 按 F5 或地址栏回车是硬刷新,强制重新请求所有资源(除非明确 Cache-Control)
- 可通过
performance.getEntriesByType('navigation')[0].type判断:-
'reload'表示硬刷新 -
'navigate'表示跳转(含地址栏输入) -
'back_forward'表示前进/后退(可能走 bfcache)
-
建议在上报时带上 entry.type,便于后续分析不同刷新方式对耗时的影响。
上报策略要轻量且防丢
生产环境中不建议每刷都上报全部字段:
- 只在
loadEventEnd > 5000(5 秒以上)或firstContentfulPaint > 3000时触发告警上报 - 使用
navigator.sendBeacon()发送,避免页面卸载导致数据丢失 - 携带基础上下文:
pathname、deviceMemory、hardwareConcurrency、isMobile
不复杂但容易忽略


















