增量更新校验必须基于完整包hash而非version_code,服务端需提供file_md5字段,客户端下载后严格比对本地文件真实md5,校验失败须触发回滚逻辑,包括读取缓存版本、解压备份包、重启应用,并配合服务端rollback_flag、expired_at和depends_on字段实现安全可控的热更新。
增量更新(hotfix)本身不改变原生包的 versionCode 或 versionName,所以仅靠服务端返回的 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),避免重复下载覆盖uni-app 没有内置热更新历史管理,所有回滚动作都依赖你主动存档。每次成功加载热更新包后,必须立刻把当前有效版本号写入 uni.setStorageSync('last_valid_hotfix', '1.2.3');同时把旧包备份到 _doc/hotfix/backup/ 目录下。
一旦校验失败或运行时报错(比如 require is not defined、Cannot find module),就说明当前热更新不可用,需立即回滚:
uni.getStorageSync('last_valid_hotfix') 获取上一个可用版本号_doc/hotfix/backup/1.2.2.zip
uni.getZipFile 解压并替换当前 _doc/hotfix/ 下的内容uni.reLaunch() 重启应用,让新资源生效在 App 冷启动阶段(即 onLaunch 中)执行 uni.reLaunch(),部分安卓机型会卡死或白屏——因为热更新资源还没加载完成,reLaunch 会清空整个 JS 上下文,导致新页面找不到模块。
正确做法是等 H5+ 环境就绪、且热更新资源已确认加载完毕后再触发:
plus.ready(() => { ... }) 内部uni.getSystemInfoSync().platform === 'android',Android 需额外加 300ms 延迟再 reLaunch
reLaunch 后立即刷新资源,应改用 location.reload(true) 强制重新加载 webview客户端无法自己判断某个热更新是否该被废弃,这个决策必须由服务端驱动。每次下发热更新包时,接口至少要返回三个关键字段:
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。所有校验、缓存、回滚动作,都要默认“当前状态不可信”,每次启动都从头验证。