WHAT - 前端性能指标(交互和响应性能指标)

文章目录

  • 一、交互和响应性能指标总览
  • 二、指标详细解析
    • [1. Input Delay](#1. Input Delay)
    • [2. Event Handlers Execution](#2. Event Handlers Execution)
    • [3. Animation Frame Rate (FPS)](#3. Animation Frame Rate (FPS))
  • [三、在 React 项目中采集交互指标](#三、在 React 项目中采集交互指标)
    • [1. 采集 Input Delay](#1. 采集 Input Delay)
    • [2. 采集 Event Handlers Execution](#2. 采集 Event Handlers Execution)
    • [3. 采集 FPS](#3. 采集 FPS)
  • 四、采集后的应用
    • [五、React 项目实战建议](#五、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 渲染/调和任务占用主线程
  • 事件委托、冒泡链较长

优化方向


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 项目中采集交互指标

这类指标可以通过 PerformanceObserverperformance.now()requestAnimationFrame 等 API 实时采集。

不像加载类指标有官方 web-vitals 包,但实现相对简单。


1. 采集 Input Delay

通过监听用户输入事件,记录从事件触发到回调执行的时间差:

ts 复制代码
// 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 });
  });
}

使用:

ts 复制代码
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:

ts 复制代码
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' },
    });
  };
}

使用时:

ts 复制代码
<button onClick={measureEventHandlerExecution(() => {
  // 一些业务逻辑
})}>Click</button>

也可以用 PerformanceObserver 监控超过 50ms 的 long tasks。


3. 采集 FPS

ts 复制代码
// 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);
}

使用:

ts 复制代码
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 / 自建上报 存储与分析交互性能
相关推荐
噢,我明白了3 小时前
前端js 常见算法面试题目详解
前端·javascript·算法
im_AMBER3 小时前
Web 开发 30
前端·笔记·后端·学习·web
Jonathan Star3 小时前
Webpack 打包优化与骨架屏结合:双管齐下提升前端性能与用户体验
前端·webpack·ux
做好一个小前端3 小时前
后端接口获取到csv格式内容并导出,拒绝乱码
前端·javascript·html
第七种黄昏3 小时前
前端面试-箭头函数
前端·面试·职场和发展
Youyzq3 小时前
前端box-shadow出现兼容性问题如何处理
前端
携欢3 小时前
PortSwigger靶场之将 XSS 存储到onclick带有尖括号和双引号 HTML 编码以及单引号和反斜杠转义的事件中通关秘籍
前端·html·xss
三小河3 小时前
工作中的Ai工具汇总
前端
mapbar_front4 小时前
react项目开发—关于代码架构/规范探讨
前端·react.js