字节 React Native 二面:RN 架构原理、直播间性能与 Agent 研发效能
- 轮次
- 二面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
RN 基础原理:
- React Native 的整体架构是怎样的?JS 线程、UI 线程、原生线程各自的职责是什么?
- setState 之后,从状态更新到页面真正渲染出来,完整流程是什么?
- RN 的 ShadowNode 是做什么的?和真实原生视图是什么关系?
- JS 和原生之间的桥接通信原理是什么?是同步还是异步?底层怎么传递数据?
- RN 不是 WebView,怎么向面试官解释这一点?
- 什么是多根实例?有什么优缺点?
- RN 组件的生命周期,类组件和函数组件在卸载阶段分别要注意哪些资源释放?
- 原生怎么给 RN 发事件?原生主动推送大量数据给 JS 会有什么问题?
- Hermes 相比旧 JS 引擎有哪些优势?
- Fabric / TurboModule 解决了老架构的什么痛点?
RN 性能与直播间业务: 11. 你认为 RN 主要的性能瓶颈在哪? 12. 直播间为什么选择 RN?为什么不全部用原生?哪些模块适合 RN、哪些绝对不适合? 13. 一个原生直播间页面上同时挂载多个 RN 浮层组件,会带来什么问题?怎么管控? 14. 多个 RN 根实例之间如何通信?有哪些方案,各自优缺点? 15. RN 内存泄漏一般有哪些常见原因?多根反复开关导致内存上涨怎么排查定位? 16. JS 线程阻塞一般是什么原因?有哪些排查手段和优化方案? 17. 频繁桥接调用会带来什么问题?可以怎么优化? 18. RN 和原生视图叠加时,手势冲突、图层穿透怎么排查解决? 19. RN 页面白屏一般有哪些原因?怎么监控、怎么兜底? 20. RN 长列表有哪些渲染问题?虚拟列表的实现思路是什么?
Agent / 研发效能: 21. Agent 整套研发效能体系,你是整体负责吗?边界是什么? 22. 从工程角度,评估一个 Agent 系统好坏要看哪些指标? 23. Agent 任务成功率上不去,怎么排查、怎么区分是大模型的问题还是 Skill/MCP/工具调用的问题? 24. 什么是 ReAct,流程是什么?有什么缺点? 25. 大模型输出 JSON 格式不稳定,你有哪些方案解决? 26. Skill 模块你是怎么设计的?Skill 之间如何编排、状态如何管理?
工程与行为: 27. 实习这三个月遇到最头疼的问题是什么?怎么排查解决,收获是什么? 28. 拿到一个性能问题,你的整体排查思路是什么? 29. 业务想快速上线但你评估会带来性能风险,你会怎么处理? 30. 客户端开发,你平时怎么持续学习?
《参考解析》
RN 的线程模型与桥接,是这一场的核心考点。 老架构里三个线程各司其职:JS 线程跑 React 的 reconciler,产出的是「UI 描述」(通过 UIManager 提交的 create/update 指令);Shadow 线程用 Yoga 做 Flexbox 布局计算,生成 ShadowNode 树(布局结果的抽象,不持有真实视图);主线程(UI 线程)负责真正创建和更新原生视图。JS 与原生之间走的是异步桥:消息被序列化成 JSON 字符串放进出队,由桥接模块在另一侧反序列化,所以既不能传函数也不能传复杂对象,也天然异步(setNativeProps 之类是特例)。桥的两个固有缺陷就是老架构的痛点:一次性序列化开销大且不可中断,高频小的桥接调用(滚动、动画、手势)会把桥打满;以及批量提交意味着 JS 卡住时 UI 完全无法响应。Fabric + TurboModule 正是为解决这两点:新渲染器用 C++ 的 Shadow Tree 做跨端共享的同步布局与「不可变」提交,支持并发渲染与优先级调度;TurboModule 用 JSI 让 JS 直接持有 C++ 对象引用、按需懒加载模块,省掉 JSON 序列化。Hermes 的价值则是把 JS 预编译成字节码,减少启动时的解析编译开销、降低内存占用,并自带更适合移动端的 GC。
直播间用 RN 的取舍要答成「用对了地方」。 适合 RN 的是迭代快、交互复杂但性能要求不极致的部分:弹窗、活动浮层、任务面板、榜单、送礼面板、配置化的运营模块——这些改动频繁,用 RN 一次开发两端复用、还能热更/动态下发。绝对不适合的是高频渲染与强实时链路:连麦音视频渲染、礼物动效的逐帧动画、大型列表的高速滚动、需要与原生深度耦合的手势与相机预览。多浮层挂载的问题在于每个 RN 实例都有独立的 JS 运行时(或至少独立的根视图)与内存开销,浮层多了会出现启动耗时叠加、内存上涨、以及事件与手势的竞争;管控手段是合并根实例、懒加载非首屏浮层、用完即销毁并复用容器、限制同时存在的浮层数量并做内存水位告警。多根之间的通信通常走原生侧的中转(Native EventEmitter)、共享的全局 Store/单例 JS 模块,或者持久化的 KV;各自的代价是时序难以保证、耦合度高,所以更好的做法是减少根的数量。
内存与阻塞类问题的排查要给出工具链。 内存泄漏的常见原因:未移除的事件监听与定时器、闭包持有大对象(图片、Base64、长列表数据)、原生模块持有 JS 引用不释放、WebView/地图等原生组件销毁不彻底;排查手段是 Android Profiler / Xcode Instruments 看堆增长与引用链、dumpsys meminfo 看进程驻留、对反复开关的场景做「开 N 次后对比内存水位」的回归。JS 线程阻塞一般来自同步计算(大 JSON 解析、复杂循环、加解密)、频繁 setState 导致的连续渲染、以及大量桥接往返;优化方向是拆包/懒执行、把重计算搬到原生或 Worker、用 InteractionManager/requestAnimationFrame 分帧、减少不必要的渲染(memo、key 稳定、避免大对象进 state)。频繁桥接优化的核心是「批量化 + 下沉」:把多次小调用合并成一次批量接口、把高频动画与手势下沉到原生驱动(useNativeDriver、Reanimated)、以及用离线计算替代每帧通信。
白屏监控与兜底要有可执行的判据。 白屏一般来自 JS 错误导致根组件挂载失败、bundle 加载失败(网络/版本不匹配)、原生视图初始化异常、或首屏数据请求超时后无兜底渲染。监控上:在根组件挂载前打点、对 bundle 加载与首屏渲染设超时上报、捕获 ErrorUtils 全局错误与原生崩溃日志,并带上版本、机型、路由与网络状态;兜底上:内置本地降级页面(原生渲染的静态页)、支持回滚到上一个可用 bundle、对关键浮层设置「超时即隐藏」而不是留在白屏状态。长列表的问题在于每个 cell 都创建视图导致内存与渲染开销线性增长,虚拟列表就是只渲染可视区 + 缓冲区的 cell,其余用空位占位;RN 里可用 FlatList 的 windowSize/initialNumToRender/removeClippedSubviews 调优,或用 FlashList、react-native-virtuoso 这类回收复用方案;配合 getItemLayout 跳过测量、以及图片懒加载与占位。
Agent 研发效能的评估与归因,答题要落到「可观测 + 可分层」。 评估一个 Agent 系统的指标分四类:效果(任务成功率、端到端正确率、人工接管率)、效率(平均步数、耗时、单任务成本)、稳定性(同输入多次运行的一致率、失败重试率、异常终止率)与体验(首字节延迟、可解释性、用户满意度)。成功率上不去的归因方法是把它当成「分段可观测」问题:给每一步(规划、检索、工具调用、生成)打点,看失败集中在哪一段;再做对照实验——固定其他变量只换模型、只换提示词、只换工具实现,观察指标变化即可区分责任方;同时人工抽样标注失败原因(模型理解错、工具返回错、上下文缺失、评测标准过严),统计各类占比。ReAct 的缺点是串行效率低、对错误观测敏感(一次错误会被写进上下文并放大)、容易在失败后重复相似动作而漂移、以及工具数量多时选择准确性下降——对应的改进是限定工具集、加校验与重规划、用状态表固定目标、以及引入并行工具调用。JSON 输出不稳定的解法:优先用厂商的原生结构化输出/工具调用(约束解码),其次用 JSON Schema 校验 + 失败重试(把校验错误回灌给模型),再不行用「只输出 JSON、不要解释」的提示词约束与 few-shot 示例,最后兜底用正则抽取与修复库(如 jsonrepair);工程上还要设重试上限与降级路径,并把解析失败率纳入监控。