主题
React 性能优化
React 页面出现长任务和交互卡顿时如何优化?
交互卡顿通常不是一个 React API 问题,而是主线程在事件、计算、渲染、布局或第三方脚本上被长时间占用。
面试官想考什么
- 什么是长任务? 考察浏览器调度基础。
- 如何定位卡顿来源? 考察 Performance 使用。
- 什么时候使用 Worker? 考察架构取舍。
- 任务拆分会不会影响结果一致性? 考察异步设计。
一句话回答
text
先用 Performance 找出占用主线程的长任务,再通过拆分计算、让低优先级更新延后、虚拟化、Worker 或服务端计算恢复输入响应。面试回答详解
1. 主线程任务来源
text
事件处理 -> JS 计算 -> React render/commit -> style/layout/paint第三方脚本、JSON 解析、正则、排序、图表和大对象序列化都可能制造长任务。
2. 优化手段
- 减少事件处理同步工作,先反馈再计算。
- 分片执行,让出主线程。
- 使用 transition 延后非紧急 React 更新。
- 把纯 CPU 计算放到 Web Worker。
- 用虚拟化、分页和增量计算减少工作量。
3. Worker 边界
Worker 适合纯计算和可序列化数据,不直接操作 DOM;通信、复制/转移成本、取消、版本和错误恢复要纳入设计。若数据本来就在服务端,服务端计算可能更合适。
4. 验证
看长任务时长、INP、输入响应、CPU 和内存,确认优化没有增加网络等待、结果延迟或数据不一致。
可直接背诵的 30 秒回答
text
我会先在 Chrome Performance 中判断长任务来自事件、React render/commit、JSON、布局还是第三方脚本。然后按成本选择方案:缩小数据和更新范围、拆分任务、transition、虚拟化、Web Worker 或服务端计算。Worker 只适合纯计算,还要处理序列化、取消和错误;最后用 INP、长任务和业务响应时间验证。扩展知识
卡顿排查
text
Performance 时间线 -> Long Task -> 调用栈
-> React Profiler -> 数据规模 -> 选择拆分方案面试官追问链
追问一:startTransition 能消除长任务吗?
- 考察点:是否理解优先级不是计算加速。
- 回答方向:不能,它能让非紧急 React 工作让路;同步 CPU 仍需拆分、缓存、Worker 或服务端处理。
追问二:Worker 传输大对象会不会更慢?
- 考察点:通信成本意识。
- 回答方向:会有结构化克隆成本;可使用 Transferable、减少数据、共享索引或把计算下沉服务端,需实测。
追问三:如何保证 Worker 结果不覆盖新输入?
- 考察点:异步竞态。
- 回答方向:给任务编号或输入版本,只接收当前版本结果,并支持取消或丢弃旧任务。