主题
React 性能优化
React 应用如何排查内存泄漏和 effect 清理问题?
内存问题往往来自组件卸载后仍被事件、订阅、定时器、请求或闭包引用,而不是 React 自动“多占内存”。
面试官想考什么
- 哪些 effect 资源必须清理? 考察副作用边界。
- 请求完成后组件卸载怎么办? 考察取消和过期结果。
- 如何证明存在内存泄漏? 考察浏览器工具。
- 严格模式暴露了什么问题? 考察幂等和清理意识。
一句话回答
text
所有由 effect 建立的订阅、监听器、定时器、Observer、连接和可取消请求都要在 cleanup 中成对释放,并用重复挂载、Heap Snapshot 和长期运行验证没有残留引用。面试回答详解
1. 常见泄漏来源
addEventListener未移除。setInterval、RAF 或 observer 未取消。- WebSocket、SSE、第三方订阅未关闭。
- 请求和异步回调持有大对象或继续回写旧状态。
- 全局缓存、闭包或 DOM 引用无限增长。
2. Effect 资源模型
text
setup -> 使用资源 -> dependency change/unmount -> cleanupcleanup 应与 setup 对称,依赖变化时先清旧资源再建立新资源。严格模式开发期的额外 setup/cleanup 能暴露不幂等实现。
3. 请求和竞态
使用 AbortController 取消可取消请求,或用版本号忽略过期结果。取消不等于服务端一定停止执行,服务端仍要支持超时和幂等。
4. 排查方式
Chrome Memory 做多次进入/离开页面的 heap snapshot,对比 detached DOM、监听器、闭包和大对象;Performance Monitor 观察长期运行趋势。不要把一次 GC 前的增长误判为泄漏。
可直接背诵的 30 秒回答
text
我会把 effect 当成资源生命周期管理:监听器、定时器、Observer、WebSocket、SSE 和请求都要在 cleanup 中释放或取消。排查时重复挂载和卸载页面,结合 Heap Snapshot、Detached DOM、监听器和长期运行曲线确认对象是否可回收;Strict Mode 下出现问题通常说明 setup/cleanup 不对称或副作用不幂等。扩展知识
资源清理清单
text
事件 -> timer/RAF -> observer -> socket/stream
-> request -> global cache -> DOM reference面试官追问链
追问一:fetch 取消后服务端一定停止了吗?
- 考察点:是否区分客户端和服务端。
- 回答方向:不一定,AbortController 主要取消客户端等待和读取;服务端需要自己的超时、取消传播和幂等控制。
追问二:为什么只在生产环境发现泄漏?
- 考察点:线上排障意识。
- 回答方向:生产运行时间更长、路由切换更多、数据量更大;应增加长期运行、页面切换和真实订阅的监控与测试。
追问三:cleanup 执行了还会泄漏吗?
- 考察点:是否理解引用链。
- 回答方向:会,可能还有全局缓存、第三方库引用、闭包或其他组件持有对象;需要看 heap retaining path。