应根据变更内容分层判断:仅前端资源(js/css/页面)更新走wgt热更新,涉及原生权限、sdk、插件或manifest配置变更则必须整包更新;服务端需同时返回apkversion和wgtversion字段,客户端分别用语义化比较和数值比较判定。

怎么判断该走 wgt 还是整包更新
uni-app 的「增量热更新」实际就是 wgt 资源包更新,它只替换 static、pages、components 等前端资源,不触碰原生层。而整包更新(apk/ipa)会覆盖整个安装包,适用于原生 SDK 升级、权限变更、iOS 17+ 新 API 适配等场景。
不能靠单一版本号字段硬比大小,必须分层判断:
-
version(如"2.3.1")用于整包升级决策:后端返回apkVersion字段,客户端用语义化比较(比如semver.gt(remote, local)),大于才触发整包提示 -
versionCode(如2310或"2310")用于wgt更新:它本质是整数,适合直接数值比对;注意 Android 和 iOS 的versionCode取值逻辑可能不同,建议统一由 manifest.json 的versionCode字段控制并透出给前端 - 服务端接口应同时返回两个字段:
apkVersion和wgtVersion,避免客户端自行拆解version字符串引发兼容问题
手动选择更新类型时的 UI 和逻辑隔离
用户点击「检查更新」后,如果后端返回两种更新都存在,不要自动跳转或静默下载——必须显式提供选择入口。常见错误是把 uni.showModal 的 confirm/cancel 直接绑定到某一种更新路径上,导致用户无法切换。
正确做法是渲染一个双选项弹窗(非系统 modal):
- 标题写清楚差异:“发现新版本,可选更新方式”
- 两个按钮分别标注:
立即更新资源(推荐,无需重装)对应wgt下载;升级完整版(含功能优化)对应整包跳转 - 点击任一按钮后,立刻禁用全部操作按钮,防止重复触发
- 整包更新路径必须调用
uni.openURL(Android)或跳转 App Store/iTunes 链接(iOS),不能尝试用plus.runtime.install加载 apk —— iOS 不允许,Android 8+ 也会因未知来源限制失败
plus.runtime.install 安装 wgt 的兼容性坑
plus.runtime.install 在不同平台和 HBuilderX 版本下行为不一致,容易卡在“安装成功但没重启”或“静默失败无回调”。关键点:
- Android 上必须确保
tempFilePath是本地绝对路径(uni.downloadFile返回的tempFilePath符合要求),不能传 http 链接 - iOS 15+ 真机环境下,
plus.runtime.install可能不触发success回调,但实际已安装;需配合plus.runtime.restart()强制重启,且重启前加setTimeout延迟 300ms,否则部分机型白屏 - HBuilderX 3.99+ 默认启用「wgt 安全校验」,若服务端 wgt 文件未用私钥签名,
install会直接报错error code: 1002;调试阶段可在 manifest.json 中临时关闭:"wgtSecure": false - 安装失败时,
fail回调里的e.message含具体原因(如"Invalid wgt file"或"Permission denied"),务必上传至日志系统,不能只 console.log
版本号比较函数不能简单 replace('.','')
把 "2.10.0" 和 "2.9.9" 转成数字比较会得出 2100 的错误结论。真实项目里必须用标准语义化版本比对逻辑:
推荐直接使用 semver 库(体积小、无副作用):
import semver from 'semver' // 检查是否需要整包更新 const needFullUpdate = semver.gt(remoteApkVersion, localVersion) // 检查是否需要 wgt 更新(versionCode 是 number) const needWgtUpdate = remoteWgtVersion > localVersionCode
如果不想引入依赖,手写也得按段拆解:
- 用
.split('.')得到数组['2','10','0']和['2','9','9'] - 逐位转
parseInt后比较,某一位大则返回 true,相等则进下一位,直到末尾 - 长度不一致时(如
"1.2"vs"1.2.0"),短的补 0 再比
别省这十几行代码——线上已有多个因版本比对翻车导致用户卡在旧版的案例。











