React Native 热更新常见问题排查:重启回滚、时间戳不一致与线上报错定位
作者是 React Native 热更新服务 Pushy(react-native-update)的维护者。本文整理了用户最常遇到的几个热更新问题和排查方法,其中原理部分对其他热更新方案同样适用。
问题一:热更新成功了,重启 App 后又回到旧版本
现象:下载、应用都提示成功,杀掉 App 重新打开,界面又变回旧版本。
原因:绝大多数情况是原生侧的 bundle URL 没有配置好。热更新的本质是让原生代码在启动时加载下载到本地的新 bundle,而不是安装包里自带的那份。如果原生侧仍然写死加载内置 bundle,那么重启后自然回到旧版本。
排查:
- 检查 iOS 的 AppDelegate 和 Android 的 MainApplication,确认 bundle URL 改成了从热更新 SDK 获取;
- Expo 48 及以上、且 react-native-update 版本不低于 10.28.2 时可以自动配置,低于这个版本要手动配置;
- 注意必须在 release 包里验证,debug 包默认从 Metro 加载代码,不会走热更新逻辑。
补充:v10 以下的旧版本还需要在启动后调用 markSuccess 标记成功,否则下次启动会被当成失败而回滚;v10 及以上版本已自动处理。
问题二:提示"热更新已暂停:编译时间戳与服务器记录不一致"
现象:同一个版本号的安装包,有的用户能收到热更新,有的收不到。
原因:每次编译原生包都会写入一个编译时间戳(buildTime)。服务端靠"版本号 + 时间戳"判断某个安装包和热更新是否匹配。如果你用同一个版本号重新打了包却没有上传,新包的时间戳在服务端查不到,为了安全,服务端会暂停给它下发热更新。
可以用命令查看安装包里的时间戳:
pushy parseIpa your-app.ipa
pushy parseApk your-app.apk
处理方法:
- 新包还没分发给用户:直接废弃,继续用已上传的那个包;
- 新包已经有用户安装:要么让这部分用户装回已上传的包,要么发一个更高版本号的原生包并上传;
- 以后的习惯:每次重新打原生包,先改版本号,再上传到服务器,最后才分发。
问题三:后台已经显示"内容指纹",为什么还是提示时间戳不匹配?
较新的版本支持用"内容指纹"(安装包内 JS bundle 的 sha256)代替时间戳做判定:同一份 JS 重复打包时按指纹放行,不再被时间戳拦截。但这需要两边同时满足:
- 上传原生包时用的 CLI(react-native-update-cli)不低于 2.8.5,服务端才会记录指纹;
- App 内集成的 react-native-update 不低于 10.49.0,客户端才会上报指纹。
后台有指纹却仍提示不匹配,几乎都是因为 App 里打包的 SDK 低于 10.49.0。升级 SDK 并重新发版后即可生效。
问题四:热更新后图片显示不出来
热更新下发的图片资源会以 file:// 协议访问。React Native 自带的 Image 组件没有问题,但部分读取资源的第三方库不支持 file:// 协议,就会出现图片或资源加载失败。遇到这种情况,先确认对应的第三方库是否支持本地文件路径。
另外要记住:原生代码、原生配置、带原生代码的第三方库升级都不能热更新,这类修改必须重新发商店版本。
问题五:线上报错了,怎么定位到源码?
热更新版本推出去后,用户反馈"某个页面白屏",最难的是拿不到能看懂的堆栈。
react-native-update 从 v10.55.0 起会自动上报热更版本里的 JavaScript 异常;发布时 CLI(2.24.2 及以上)会自动归档 sourcemap,后台的报错详情会把压缩后的堆栈还原到 src/xxx.ts:18:17 这样的源码位置,并显示出错行前后的代码。
业务代码里也可以主动上报:
try {
await submitOrder(order);
} catch (e) {
pushyClient.captureException(e, {
extra: { screen: "checkout", orderId: order.id },
});
}
几点注意:
- 只有运行在热更版本上的报错会上报;安装包自带 bundle 的崩溃请用 Sentry、Crashlytics 等工具;
- SDK 是在全局 ErrorUtils 处理器上追加一层,不会影响已有的 Sentry、Crashlytics;
- 如果提示"该热更版本没有归档 sourcemap",通常是 CLI 版本过旧,或者自定义打包后用
pushy publish手动发布时没带--sourcemap参数。
问题六:怎么知道热更新到底有多少人生效了?
“已下发"不等于"已生效”。排查覆盖率问题时,建议按这个顺序看:
- 请求结果构成:有多少请求返回"已是最新"、多少走了增量、多少因为原生包未登记或版本过期没拿到更新;
- 版本漏斗:某个热更版本的"下发 → 下载成功 → 激活 → 回滚",并按原生包拆开看,定位是不是某个安装包有问题;
- 失败原因:超时、网络错误、磁盘空间不足、校验不一致、补丁应用失败等,再按系统版本和运营商对比,看是否集中在某类环境。
Pushy 后台的「数据分析」页面提供了上述视图,可以直接区分"没命中更新""下载失败"和"已下载但还没生效"这几种情况。
参考
- Pushy 文档:https://pushy.reactnative.cn/docs/getting-started
- 常见问题:https://pushy.reactnative.cn/docs/faq
- GitHub:https://github.com/reactnativecn/react-native-update
更多推荐


所有评论(0)