WHAT - 前端性能指标(交互和响应性能指标)
文章目录
- 一、交互和响应性能指标总览
- 二、指标详细解析
- 1. Input Delay
- 2. Event Handlers Execution
- 3. Animation Frame Rate (FPS)
- 三、在 React 项目中采集交互指标
- 1. 采集 Input Delay
- 2. 采集 Event Handlers Execution
- 3. 采集 FPS
- 四、采集后的应用
- 五、React 项目实战建议
在 WHAT - 前端性能指标 中我们简单介绍了几类前端性能指标。今天我们主要介绍第四类指标。
这类指标是 用户感知性能 中最直接的部分,往往决定了一个网站是否“流畅、不卡顿”。
它们不同于加载性能,更关注页面 加载完成之后的体验质量,特别是输入、点击、滚动、动画等交互。
一、交互和响应性能指标总览
指标 | 含义 | 推荐阈值 | 描述 |
---|---|---|---|
Input Delay | 用户输入延迟 | ≤ 100ms(优秀) | 用户触发交互(点击、输入)到浏览器响应的延迟 |
Event Handlers Execution | 事件处理耗时 | ≤ 50ms(理想) | 事件处理函数执行耗时 |
Animation Frame Rate (FPS) | 动画帧率 | ≥ 60 FPS(理想) | 每秒渲染的帧数,反映页面交互和动画流畅度 |
二、指标详细解析
1. Input Delay
定义:Input Delay 衡量用户触发交互(点击、输入、滚动等)到浏览器真正开始执行事件处理的延迟。本质上受主线程是否被阻塞影响,是 FID 的延伸和更精细的 RUM 指标。
推荐值:
优秀:≤ 100 ms
可接受:100–300 ms
较差:> 300 ms
影响因素:
- 主线程正在执行长任务(Long Task)
- JS 执行体积大、同步逻辑多
- React 渲染/调和任务占用主线程
- 事件委托、冒泡链较长
优化方向
- 拆分 JS bundle,减少同步执行。具体可以阅读 HOW - 如何使用 bundle-analyzer 工具优化包体积
- 使用 requestIdleCallback 处理非关键任务。具体可以阅读 WHAT - requestIdleCallback 介绍
- 使用 Web Worker 分担计算。具体可以阅读 WHAT - 前端 Web Worker 和 Service Worker(含工作者线程概念)
- 减少组件层级和重渲染
2. Event Handlers Execution
定义:Event Handlers Execution 是指浏览器调用你的事件处理函数,并完成执行的耗时。如果执行时间过长,会阻塞后续帧的渲染,导致交互“卡顿”。
推荐值:
理想:≤ 50 ms
较差:> 100 ms
影响因素:
- 事件处理逻辑复杂(循环、计算、DOM 操作)
- 触发频率高(如 scroll、mousemove)
- 多次 setState 导致多轮渲染
优化方向:
- 减少事件处理中的同步计算
- 节流、防抖高频事件
- 使用 useMemo / useCallback 优化 React 组件
- DOM 操作使用批处理(batch update)
3. Animation Frame Rate (FPS)
定义:FPS(Frames Per Second)是衡量动画和交互流畅度的核心指标。
浏览器理想帧率为 60 FPS,意味着一帧渲染时间 ≈ 16.67 ms。如果渲染超过这个时间,就会掉帧或卡顿。
推荐值
优秀:≥ 55–60 FPS
可接受:40–55 FPS
较差:< 40 FPS
影响因素:
- JS 执行占用过长
- 页面需要重绘/重排的元素太多
- 动画未使用 GPU 加速(transform/opacity)
- 滚动、拖拽逻辑繁重
优化方向
- 使用 transform/opacity 进行动画(避免 layout)
- 使用 CSS 动画代替 JS 动画
- 使用 requestAnimationFrame 控制 JS 动画
- 通过虚拟滚动、惰性渲染减少 DOM 数量
- 避免强制同步布局
具体可以阅读 WHAT - CSS Animationtion 动画系列(三)- 动画卡顿分析
三、在 React 项目中采集交互指标
这类指标可以通过 PerformanceObserver、performance.now()
、requestAnimationFrame
等 API 实时采集。
不像加载类指标有官方 web-vitals 包,但实现相对简单。
1. 采集 Input Delay
通过监听用户输入事件,记录从事件触发到回调执行的时间差:
// src/utils/inputDelay.ts
export function monitorInputDelay(callback: (delay: number) => void) {const listener = (e: Event) => {const eventTime = e.timeStamp;const now = performance.now();const delay = now - eventTime;callback(delay);};['click', 'keydown', 'pointerdown', 'touchstart'].forEach((type) => {window.addEventListener(type, listener, { passive: true });});
}
使用:
import { monitorInputDelay } from './utils/inputDelay';monitorInputDelay((delay) => {console.log('Input Delay:', delay);fetch('/api/performance', {method: 'POST',body: JSON.stringify({ metric: 'inputDelay', value: delay }),headers: { 'Content-Type': 'application/json' },});
});
2. 采集 Event Handlers Execution
可以在事件回调中手动记录开始和结束时间,也可以通过 PerformanceObserver 监听 longtask:
export function measureEventHandlerExecution(fn: Function) {return (...args: any[]) => {const start = performance.now();fn(...args);const end = performance.now();const duration = end - start;console.log('Event handler execution time:', duration);fetch('/api/performance', {method: 'POST',body: JSON.stringify({ metric: 'eventHandlerExecution', value: duration }),headers: { 'Content-Type': 'application/json' },});};
}
使用时:
<button onClick={measureEventHandlerExecution(() => {// 一些业务逻辑
})}>Click</button>
也可以用 PerformanceObserver 监控超过 50ms 的 long tasks。
3. 采集 FPS
// src/utils/fpsMonitor.ts
export function monitorFPS(callback: (fps: number) => void) {let lastFrameTime = performance.now();let frameCount = 0;function loop() {const now = performance.now();frameCount++;if (now >= lastFrameTime + 1000) {const fps = (frameCount * 1000) / (now - lastFrameTime);callback(fps);frameCount = 0;lastFrameTime = now;}requestAnimationFrame(loop);}requestAnimationFrame(loop);
}
使用:
import { monitorFPS } from './utils/fpsMonitor';monitorFPS((fps) => {console.log('FPS:', fps);fetch('/api/performance', {method: 'POST',body: JSON.stringify({ metric: 'fps', value: fps }),headers: { 'Content-Type': 'application/json' },});
});
四、采集后的应用
场景 | 指标 | 问题 | 优化方向 |
---|---|---|---|
点击响应慢 | Input Delay | JS 阻塞主线程 | 减少同步任务、拆包、Worker |
点击后页面卡顿 | Event Handler Execution | 逻辑复杂 | 减少计算量,节流 |
动画掉帧 | FPS | 渲染压力大 | GPU 加速、CSS 动画、虚拟滚动 |
五、React 项目实战建议
技术 | 应用 |
---|---|
Performance.now + 事件监听 | 采集 Input Delay |
包装事件处理函数 | 采集 handler 执行耗时 |
requestAnimationFrame | 实时计算 FPS |
PerformanceObserver | 监控 long tasks |
Sentry / 自建上报 | 存储与分析交互性能 |