React Native 0.71-RC0 Android 构建中断事故分析
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
随着 0.71 正式版的发布,我们有必要说明在 2022 年 11 月 4 日发布首个 React Native 和 Expo Android 构建的 0.71 候选版本时,导致所有 React Native 版本 Android 构建中断的具体情况。
参与处理该事故的贡献者近期召开了复盘会议,详细讨论了事故原因、经验教训以及未来避免类似故障的改进措施。
事故经过
2022 年 11 月 4 日,我们在多个公共仓库发布了 React Native 0.71.0-rc0 版本,这是 0.71 的首个候选版本。
该候选版本的重大变更是将工件发布至 Maven Central 而非从源码构建,从而提升构建速度。具体实施方案详见 RFC#508 及 相关讨论。
遗憾的是,由于项目模板初始化新工程的方式存在缺陷,所有使用旧版本的用户在构建时开始下载 0.71.0-rc0 的新工件(而非其项目实际使用的版本如 0.68.0),导致构建失败。
根本原因
React Native 模板提供的 build.gradle 文件包含如下 Android 依赖声明:
implementation("com.facebook.react:react-native:+").
其中的 + 符号(即 Gradle 动态版本)会指示 Gradle 自动选择最高版本的 React Native。使用动态版本被视为反模式,因其可能导致构建结果不可复现。
我们知晓动态版本可能引发的问题,因此在 0.71 版本中清理了新应用模板并移除了所有 + 依赖声明。但旧版本用户仍在使用含 + 的模板。
这导致所有低于 0.71.0-rc.0 的 React Native 版本在构建时自动检索仓库中可用的最高版本。由于新发布的 0.71.0-rc.0 成为最高版本,低于此版本的构建开始错误使用 0.71.0-rc.0 的工件。本地构建版本(如 0.68.0)与 Maven Central 工件版本(0.71.0-rc.0)不匹配最终导致构建失败。
该事件的技术细节可参阅 GitHub 相关 issue。
应对措施
11 月 4 日确认问题后,社区迅速找到并分享了手动解决方案:通过指定确切版本号修复依赖声明。
随后在 11 月 5 日至 6 日的周末,发布团队为所有历史版本(下至 0.63)推送了补丁更新,自动修复该问题,用户只需更新至修复后的 React Native 版本即可。
与此同时,我们 联系了 Sonatype 请求移除问题工件。
11 月 8 日问题工件从 Maven Central 彻底移除后,事故完全解决。
时间线
本节简要记录了事件时间线,所有时间均为 GMT/UTC+0 时区
-
11月4日 17:06: 发布 0.71-RC0 版本
-
11月4日 18:20: 首次提交构建问题报告
-
11月4日 19:45: 社区确认问题根源
-
11月4日 21:39: 公布临时解决方案,Expo 为所有用户部署修复
-
11月5日 03:04: 新建问题追踪专页同步状态和解决方案
-
11月6日 16:11: 向 Sonatype 提交工单请求移除问题构件
-
11月6日 16:40: @reactnative 官方账号首次推文确认问题并附解决方案链接
-
11月6日 19:05: 决定为 0.63 及以上版本发布补丁
-
11月7日 00:47: 最后一个补丁版本 0.63.5 发布
-
11月8日 20:04: Maven Central 问题构件完成移除
-
11月10日 11:51: 问题追踪专页关闭
经验总结
虽然引发本次事故的技术隐患自 React Native 0.12.0 版本就已存在,我们将确保未来开发和发布流程的基础更加牢固。以下是本次事件的经验总结及后续改进措施:
事件响应策略
本次事件暴露了我们在处理 React Native 开源项目相关事故时的响应策略缺陷。
社区在 2 小时内快速找到了临时解决方案。但由于缺乏对问题影响范围的实时评估能力,以及为旧版本修复的技术复杂度,我们当时依赖受影响用户自行在 GitHub 问题页发现解决方案。
耗时 48 小时后,我们才意识到该问题的广泛影响范围,并认识到不能依赖所有用户自行查找 GitHub 解决方案。因此必须优先实施更复杂的主动修复方案来自动修复用户项目。
我们将重新评估"依赖开发者手动应用临时方案"与"部署自动修复"的决策标准,同时探索获取生态系统健康实时数据的可行方案。
版本支持策略
通过 rn-versions 工具可视化数据可见,为覆盖事故发生时 90% 以上的 React Native 开发者群体,我们必须向下兼容至 0.63 版本发布补丁。
我们认为这是由于 React Native 的升级体验历来充满摩擦所致。我们正在研究改进升级体验的方法,使其更顺畅、更快速,以缓解生态系统碎片化的问题。
发布新版本的 React Native 绝不应影响使用旧版本的用户,对于此次事件对您工作流程造成的干扰,我们深表歉意。
同时,我们也想强调保持依赖项和 React Native 最新版本的重要性,这样才能受益于我们引入的改进和安全措施。该事件发生时,官方的版本支持政策正处于制定阶段,尚未正式公布或强制执行。
未来,我们将通过官方渠道公布支持政策,并考虑在 npm 上弃用旧版 React Native。
改进第三方库测试和最佳实践
此事件凸显了改进发布测试和优化第三方库指导的重要性。
在测试方面,由于缺乏稳定版本现有的自动化流程和测试机制,发布向下兼容至 0.63.x 的版本面临巨大挑战。我们认识到发布和测试基础设施的重要性,未来将加大投入力度。
具体而言,我们现在鼓励并将支持将第三方库测试纳入 React Native 发布流程。同时我们还在核心贡献者 Discord 服务器中新增了沟通渠道和角色。
此外,我们与 create-react-native-library 的维护方 Callstack 展开了深度合作,旨在改进库模板并确保其遵循所有必要的最佳实践以实现与 React Native 项目的无缝集成。新版本的 create-react-native-library 现已完全兼容 0.71 项目,同时保持向后兼容性。
总结
我们为此次事件给全球开发者工作流程造成的干扰深表歉意。如上所述,我们已开始采取行动巩固基础架构——更多工作正在进行中。
希望通过分享这些见解,能帮助大家更好地理解本次事件,并能借鉴我们的经验教训,在您自己的工具和项目中应用更佳实践。
最后,我们要再次感谢 Sonatype 协助我们移除问题构件,感谢社区成员和发布团队为此事件不眠不休的及时响应。

