应优先使用 performance.getentriesbytype('navigation') 获取 performancenavigationtiming 实例,fallback 到 performance.navigationstart 或 date.now();避免依赖已废弃的 performance.timing,禁用 window.onload 时机测量,改用 performanceobserver 捕获 fp/fcp,并结合 resource 耗时与 performance.now() 精确监控。

直接用 performance.timing 会踩兼容性坑
IE9+、Chrome11+、Firefox7+ 支持 performance.timing,但 Safari(包括 iOS QQ 浏览器)基本不支持,且该接口已被标记为废弃。实际项目中如果只依赖它,navigationStart 可能返回 0 或 undefined,导致计算结果为负数或 NaN。
更稳妥的做法是 fallback 到 performance.navigationStart(注意不是 timing.navigationStart),它是 PerformanceNavigationTiming 的一部分,现代浏览器普遍支持:
const navStart = performance.navigationStart || (performance.timing && performance.timing.navigationStart) || Date.now();
- 优先用
performance.navigationStart(推荐,规范、稳定) - 降级到
performance.timing.navigationStart(仅用于旧版 Chrome/Firefox) - 最后 fallback 到
Date.now()(极端情况,比如页面刚打开就执行 JS)
performance.getEntriesByType('navigation') 是首选方案
相比读取已废弃的 timing 对象,getEntriesByType('navigation') 返回的是标准的 PerformanceNavigationTiming 实例,字段更清晰、语义更明确,且自带精度保障(微秒级)。
典型用法:
const navEntries = performance.getEntriesByType('navigation');<br>if (navEntries.length > 0) {<br> const nav = navEntries[0];<br> console.log('TTFB:', nav.responseStart - nav.requestStart);<br> console.log('FCP:', nav.domContentLoadedEventStart - nav.startTime);<br> console.log('LCP:', nav.loadEventEnd - nav.startTime);<br>}
-
nav.startTime等价于navigationStart,是本次导航的绝对起点 -
responseStart和requestStart直接给出首字节时间(TTFB),比手动算timing更可靠 - 若页面是缓存加载(
nav.type === 'back_forward'),responseStart可能为0,需判断后跳过
别在 window.onload 里才开始测 —— 太晚了
window.onload 触发时,图片、字体、异步脚本等资源早已加载完毕,此时再读 performance 数据,虽然能拿到完整值,但已经错过关键瓶颈点(比如 TTFB 高、JS 执行阻塞渲染)。真正要监控的,是用户“看到内容”的时间,而不是“所有资源加载完”的时间。
正确时机:
- 页面顶部立即执行:获取
performance.navigationStart并打点 - 监听
performance.getEntriesByType('paint')捕获 FP/FCP(需配合PerformanceObserver) - 对首屏关键元素(如
<img>或容器div)用IntersectionObserver判断是否可见
例如快速捕获 FCP:
new PerformanceObserver((list) => {<br> for (const entry of list.getEntries()) {<br> if (entry.name === 'first-contentful-paint') {<br> console.log('FCP:', entry.startTime);<br> observer.disconnect();<br> }<br> }<br>).observe({entryTypes: ['paint']});
移动端 WebView 中 performance.memory 基本不可用
很多开发者想通过 performance.memory 查看内存压力来辅助判断卡顿,但在 Android WebView 和 iOS WKWebView 中,该属性多数被禁用或返回 undefined。即使存在,其数值也仅反映 JS 堆内存,不包含渲染进程、图片解码、GPU 缓存等真实瓶颈来源。
替代思路:
- 用
performance.getEntriesByType('resource')查看大图、字体、JS 文件的加载耗时和大小 - 结合
requestIdleCallback监控主线程空闲程度 - 在关键操作前后调用
performance.now()测量 JS 执行耗时(比Date.now()精确 100 倍以上)
比如测一段渲染逻辑:
const start = performance.now();<br>renderMyList();<br>console.log(`render took ${performance.now() - start}ms`);
真正难的不是取到数字,而是理解每个字段背后代表的真实用户感知阶段 —— 比如 domInteractive 不等于可交互,loadEventEnd 不等于首屏完成。这些边界条件,在弱网、低端机、WebView 场景下尤其容易误判。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











