微信小程序无真正静默更新,下载完成需用户手动重启;onupdateready后必须用showmodal弹窗触发applyupdate,不可用toast或自定义弹窗替代;版本比对须用wx.getaccountinfosync().miniprogram.version与服务端语义化比较。

微信小程序没有真正意义上的“静默更新”——它不支持后台自动安装、不提供版本号直接比对 API,所谓“静默”仅指下载过程对用户不可见,但最终必须由用户主动触发重启。强制重启是可行的,且是官方唯一推荐的强制更新路径。
为什么 uni.getUpdateManager().onUpdateReady 必须配合 showModal 弹窗
微信小程序更新机制分三步:检查 → 下载 → 准备就绪。onUpdateReady 事件只表示新版本已下载完成并可应用,但不会自动生效;不弹窗提示、不调用 applyUpdate(),用户继续使用旧版本,新资源永远不加载。
- 直接在 onUpdateReady 里调用
updateManager.applyUpdate()会失败(微信限制,必须由用户手势触发) - 弹窗是绕过该限制的唯一合法方式,
uni.showModal属于用户主动交互,满足触发条件 - 不能用
uni.showToast或 cover-view 自定义弹窗替代,它们不构成“确定类交互”,applyUpdate 仍会被拦截
如何安全获取当前版本号并避免字符串比较陷阱
小程序端无法通过 plus.runtime.version 获取 App 版本(5+ API 不可用),也不能依赖 uni.getSystemInfoSync().version(它返回的是微信客户端版本,不是你的小程序版本)。正确做法是:用 wx.getAccountInfoSync() 拿到 miniProgram.version,再和服务端返回的最新版本做语义化比对。
- 服务端返回的 version 字段必须是纯数字格式(如
"1.2.3"),禁止带v前缀、字母或空格 - 本地取值必须用
wx.getAccountInfoSync().miniProgram.version,不能用uni.getSystemInfoSync().version - 比对必须用
semver.gt(newVer, curVer)或手写分段转数字逻辑,例如"1.10.0" > "1.9.0"字符串比较结果为 false,但数值上明显是新版
强制更新弹窗的时机与路由拦截怎么做
不能在 onLaunch 立即弹窗,否则用户还没看到首页就卡住;也不能等用户进设置页才检查——强制更新必须拦在关键路径前。推荐在 onShow 中发起检查,并用全局状态控制后续跳转。
- 首次检查成功后,若服务端返回
force: true且本地版本低于目标版本,立即设置globalData.updatePending = true - 所有页面的
onLoad或路由守卫中检查该标志,若为 true,则uni.redirectTo({ url: '/pages/update-pending' })跳转至全屏提示页 - 提示页内不再重复检查,只渲染固定文案 + “立即重启”按钮,点击后调用
updateManager.applyUpdate() - 不要用
setTimeout延迟弹窗,微信对非即时交互的 applyUpdate 调用会静默拒绝
安卓真机调试时 onUpdateFailed 总被忽略怎么办
这个回调常不触发,不是代码问题,而是微信底层行为:当网络中断、证书错误或 CDN 缓存脏包时,下载可能静默失败,onUpdateFailed 却没执行。必须额外监听 onCheckForUpdate 的 hasUpdate 和 onUpdateReady 是否如期到达。
- 如果
onCheckForUpdate返回hasUpdate: true,但超过 30 秒未触发onUpdateReady,大概率下载卡住,应主动降级为手动重试逻辑 - 失败后不要只显示“请重装”,而要提供
uni.reLaunch({ url: '/pages/index' })回首页 + 底部加一行小字:“稍后重试更新” - 真机测试务必关掉开发工具的“刷新时重新编译”,否则热重载会干扰 updateManager 生命周期
最易被忽略的一点:微信正式版更新存在 24–48 小时全量灰度期,你在管理后台发布了新版,但部分用户设备仍拉不到新包——这不是代码 bug,是平台机制。上线前务必用体验版 + 真机扫码验证全流程,别只信开发工具模拟。











