一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

uni-app如何实现App端的增量热更新版本自动校验回滚

时间:2026-07-02 12:04:58 编辑:袖梨 来源:一聚教程网

增量更新校验必须基于完整包hash而非version_code,服务端需提供file_md5字段,客户端下载后严格比对本地文件真实md5,校验失败须触发回滚逻辑,包括读取缓存版本、解压备份包、重启应用,并配合服务端rollback_flag、expired_at和depends_on字段实现安全可控的热更新。

增量更新的校验必须基于完整包 hash,不能只比 version_code

增量更新(hotfix)本身不改变原生包的 versionCodeversionName,所以仅靠服务端返回的 version_code 无法判断热更新是否已生效或是否损坏。真正需要校验的是热更新包的完整性——也就是它的内容 hash。

常见错误是把热更新当成普通版本升级来处理:拉一次接口、比一次 version_code、然后直接执行 uni.reLaunch()。结果用户看到白屏、功能异常,却查不出原因。

  • 服务端必须为每个热更新包提供 file_md5 字段(不是 base64 或 sha256,统一用 md5 小写 32 位)
  • 客户端下载后必须调用 uni.getFileInfo 获取本地文件真实 md5,与服务端返回值严格比对
  • 校验失败时,不能跳过、不能静默重试,必须触发回滚逻辑
  • 热更新包路径建议固定为 _doc/hotfix/ + version_name(如 _doc/hotfix/1.2.3.zip),避免重复下载覆盖

回滚到上一个热更新版本要靠本地缓存 + manifest 记录

uni-app 没有内置热更新历史管理,所有回滚动作都依赖你主动存档。每次成功加载热更新包后,必须立刻把当前有效版本号写入 uni.setStorageSync('last_valid_hotfix', '1.2.3');同时把旧包备份到 _doc/hotfix/backup/ 目录下。

一旦校验失败或运行时报错(比如 require is not definedCannot find module),就说明当前热更新不可用,需立即回滚:

  • 读取 uni.getStorageSync('last_valid_hotfix') 获取上一个可用版本号
  • 拼出对应备份路径,如 _doc/hotfix/backup/1.2.2.zip
  • uni.getZipFile 解压并替换当前 _doc/hotfix/ 下的内容
  • 最后调用 uni.reLaunch() 重启应用,让新资源生效
  • 注意:iOS 上解压 zip 后需手动删除旧 js 文件再写入,否则可能缓存残留

强制回滚时要避开 uni.reLaunch 的冷启动陷阱

在 App 冷启动阶段(即 onLaunch 中)执行 uni.reLaunch(),部分安卓机型会卡死或白屏——因为热更新资源还没加载完成,reLaunch 会清空整个 JS 上下文,导致新页面找不到模块。

正确做法是等 H5+ 环境就绪、且热更新资源已确认加载完毕后再触发:

  • 必须包裹在 plus.ready(() => { ... }) 内部
  • 回滚前检查 uni.getSystemInfoSync().platform === 'android',Android 需额外加 300ms 延迟再 reLaunch
  • iOS 不支持 reLaunch 后立即刷新资源,应改用 location.reload(true) 强制重新加载 webview
  • 回滚失败时降级为 toast 提示 + 手动重启按钮,不要无限循环尝试

服务端配合:热更新包必须带 rollback_flag 和 expired_at

客户端无法自己判断某个热更新是否该被废弃,这个决策必须由服务端驱动。每次下发热更新包时,接口至少要返回三个关键字段:

  • rollback_flag: true —— 表示该包已被标记为异常,客户端收到后应立即回滚并清除本地缓存
  • expired_at: '2026-06-18T12:00:00Z' —— 过期时间,客户端启动时需校验,超时则自动丢弃并回滚
  • depends_on: '1.2.2' —— 显式声明依赖的基线版本,若本地没有该基线,则拒绝加载,直接回滚到最近兼容版本
  • 注意:depends_on 必须和 manifest.json 中的 versionName 格式完全一致(如 "1.2.2",不能是 "v1.2.2""1.2.2-beta"

真正的难点不在代码怎么写,而在于热更新和原生包的生命周期必须解耦——你永远不知道用户上次更新是半年前还是五分钟前,也不清楚他中间跳过了几个 hotfix。所有校验、缓存、回滚动作,都要默认“当前状态不可信”,每次启动都从头验证。

热门栏目