Files
zhuangang/topics/frontend/fe-testing-perf/scenarios/perf-regression.md
T

3.7 KiB
Raw Blame History

id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week
id title type domain stack tags level prerequisites est_hours related week
frontend.fe-testing-perf.scenario.perf-regression 性能治理:真实用户监控、定位慢页面、CI 性能预算和测试防回归 scenario frontend
fe-testing-perf
cicd
性能监控
RUM
Lighthouse CI
性能预算
回归测试
INP
intermediate
frontend.fe-testing-perf.web-vitals
frontend.fe-testing-perf.testing
2.5
frontend.fe-testing-perf.interview
frontend.webpack.scenario.build-speed
7

性能治理:真实用户监控、定位慢页面、CI 性能预算和测试防回归

业务背景与问题

SaaS 客服工作台(Vue / React 单页应用):客户投诉“越用越卡”,坐席在工单列表和 AI 回复面板之间切换时明显卡顿;每次大促前临时优化,之后又退化;没人说得清哪个页面、哪类设备慢。

约束

  • 不能大规模重写。
  • 坐席电脑配置参差不齐。
  • 需要用数据向业务方说明优化效果。

方案设计

  1. 可观测:上线 RUM 采集 LCP / INP / CLS + 页面路径 + 版本号 + 设备信息;按页面和版本看 75 分位;同时采集长任务(Long Animation Frames / Long Tasks API,以 MDN 为准)。
  2. 定位:从 INP 最差的页面入手,在性能面板录制,找到长任务的调用栈。常见发现:
    • 工单列表一次渲染上千行 → 虚拟列表;
    • AI 回复每个 token 重新渲染整个面板 → 批量合并更新 + 局部渲染;
    • 全局状态变化导致整页重新渲染 → 拆分状态、记忆化。
  3. 防退化:
    • CI 中对关键页面跑 Lighthouse(实验室数据)设置预算,超出则失败;
    • 产物体积预算;
    • 对“竞态、防抖、批量更新”等逻辑写单元 / 组件测试;
    • 每个版本对比 RUM 指标,退化告警。
  4. 汇报:用优化前后同类设备的 75 分位对比说明效果。

关键代码

批量合并流式 token,降低渲染频率:

export function createBatcher(flush: (text: string) => void, intervalMs = 50) {
  let buffer = "";
  let timer: ReturnType<typeof setTimeout> | null = null;
  return {
    push(token: string) {
      buffer += token;
      timer ??= setTimeout(() => {      // 一个时间窗口内的 token 合并成一次渲染
        flush(buffer);
        buffer = "";
        timer = null;
      }, intervalMs);
    },
    end() {
      if (timer) clearTimeout(timer);
      if (buffer) flush(buffer);
      buffer = "";
      timer = null;
    },
  };
}

防抖与竞态的组件测试:examples/search-box。

取舍

选择 优点 缺点
RUM + 实验室预算(本方案) 既知道真实情况,又能在合并前拦截退化 需要搭建采集和看板
只用 Lighthouse 简单 与真实用户体验有差距,尤其是 INP
使用第三方性能监控平台 开箱即用 成本、数据合规(客服数据不能随便上报)

易错点

  • 上报数据中带了客户的敏感信息(URL 参数中的手机号、工单内容)。
  • 只看平均值。
  • 批量渲染的定时器在组件卸载时没有清理。
  • 优化了实验室分数,真实 INP 没变化:交互卡顿往往在登录后的复杂页面,Lighthouse 默认测不到。

面试怎么讲

“先建立度量:线上采集 Web Vitals 按页面和版本看 75 分位,发现工作台的 INP 最差。用性能面板定位到两个长任务:工单列表全量渲染和 AI 回复逐 token 重渲染,分别改成虚拟列表和 50ms 批量更新。然后在 CI 加 Lighthouse 和体积预算、给关键交互逻辑写测试防止退化。效果用优化前后同类设备的 75 分位对比(数据以实测为准)。”