作者是 React Native 热更新服务 Pushy(react-native-update)的维护者。本文整理了用户最常遇到的几个热更新问题和排查方法,其中原理部分对其他热更新方案同样适用。

问题一:热更新成功了,重启 App 后又回到旧版本

现象:下载、应用都提示成功,杀掉 App 重新打开,界面又变回旧版本。

原因:绝大多数情况是原生侧的 bundle URL 没有配置好。热更新的本质是让原生代码在启动时加载下载到本地的新 bundle,而不是安装包里自带的那份。如果原生侧仍然写死加载内置 bundle,那么重启后自然回到旧版本。

排查:

  1. 检查 iOS 的 AppDelegate 和 Android 的 MainApplication,确认 bundle URL 改成了从热更新 SDK 获取;
  2. Expo 48 及以上、且 react-native-update 版本不低于 10.28.2 时可以自动配置,低于这个版本要手动配置;
  3. 注意必须在 release 包里验证,debug 包默认从 Metro 加载代码,不会走热更新逻辑。

补充:v10 以下的旧版本还需要在启动后调用 markSuccess 标记成功,否则下次启动会被当成失败而回滚;v10 及以上版本已自动处理。

问题二:提示"热更新已暂停:编译时间戳与服务器记录不一致"

现象:同一个版本号的安装包,有的用户能收到热更新,有的收不到。

原因:每次编译原生包都会写入一个编译时间戳(buildTime)。服务端靠"版本号 + 时间戳"判断某个安装包和热更新是否匹配。如果你用同一个版本号重新打了包却没有上传,新包的时间戳在服务端查不到,为了安全,服务端会暂停给它下发热更新。

可以用命令查看安装包里的时间戳:

pushy parseIpa your-app.ipa
pushy parseApk your-app.apk

处理方法:

  • 新包还没分发给用户:直接废弃,继续用已上传的那个包;
  • 新包已经有用户安装:要么让这部分用户装回已上传的包,要么发一个更高版本号的原生包并上传;
  • 以后的习惯:每次重新打原生包,先改版本号,再上传到服务器,最后才分发。

问题三:后台已经显示"内容指纹",为什么还是提示时间戳不匹配?

较新的版本支持用"内容指纹"(安装包内 JS bundle 的 sha256)代替时间戳做判定:同一份 JS 重复打包时按指纹放行,不再被时间戳拦截。但这需要两边同时满足:

  1. 上传原生包时用的 CLI(react-native-update-cli)不低于 2.8.5,服务端才会记录指纹;
  2. 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 参数。

问题六:怎么知道热更新到底有多少人生效了?

“已下发"不等于"已生效”。排查覆盖率问题时,建议按这个顺序看:

  1. 请求结果构成:有多少请求返回"已是最新"、多少走了增量、多少因为原生包未登记或版本过期没拿到更新;
  2. 版本漏斗:某个热更版本的"下发 → 下载成功 → 激活 → 回滚",并按原生包拆开看,定位是不是某个安装包有问题;
  3. 失败原因:超时、网络错误、磁盘空间不足、校验不一致、补丁应用失败等,再按系统版本和运营商对比,看是否集中在某类环境。

Pushy 后台的「数据分析」页面提供了上述视图,可以直接区分"没命中更新""下载失败"和"已下载但还没生效"这几种情况。

参考

  • Pushy 文档:https://pushy.reactnative.cn/docs/getting-started
  • 常见问题:https://pushy.reactnative.cn/docs/faq
  • GitHub:https://github.com/reactnativecn/react-native-update
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐