plus.runtime.install 必须配合 plus.runtime.restart,因为 install 仅解压新 wgt 包到私有目录,不重启则 JS 引擎、Vue 实例、缓存等仍运行旧代码,界面无变化甚至白屏或 404。

plus.runtime.install 为什么必须配合 plus.runtime.restart
热更新不是“覆盖文件就生效”,plus.runtime.install 只是把新 wgt 包解压进应用私有目录,但当前运行的 JS 引擎、Vue 实例、缓存资源仍指向旧版本。不重启,所有页面、组件、API 调用都还在老代码里跑。
-
plus.runtime.restart()是强制卸载当前 Webview 容器并重新加载整个webview栈,确保从index.html开始走新资源的初始化流程 - 如果只调用
install而忘记restart,你会看到控制台打印 “install success”,但界面完全没变化,甚至可能因新旧 JS 混用导致路由白屏或接口 404 - Android 上部分低版本(如 5+ SDK 2.6.10 之前)在后台静默安装后不重启,会导致下次启动时加载失败——此时
restart不仅是推荐,而是必须
manifest.json 版本号校验失败的三个常见原因
plus.runtime.install 默认开启版本校验(force: false),它比对的是 manifest.json 中的 versionName 字段,不是你代码里写的变量或打包时间戳。
- 服务器返回的
wgtUrl对应的包,其manifest.json的versionName必须严格大于当前 App 的versionName(比如"1.2.3"→"1.2.4",不能是"1.2.3-hotfix"这种非语义化格式) - HBuilderX 打包 wgt 时若勾选了「使用自定义 manifest.json」但路径错误,或未同步修改工程根目录下的
manifest.json,会导致生成的 wgt 仍含旧版本号 - 真机调试时用的是开发基座(debug base),它的
versionName固定为"1.0.0",和正式包不一致——热更新逻辑务必用#ifdef APP-PLUS包裹,且只在正式打包环境启用
uni.request 检测接口返回后,wgt 下载常卡在 200 但 install 失败
HTTP 状态码 200 只代表文件下载完成,不代表 wgt 包本身合法。很多失败发生在解压或校验阶段,错误信息藏在 install 的失败回调 e 里,而不是网络层。
- 典型报错:
"Invalid wgt package: no manifest.json"—— 说明 wgt 压缩包根目录下没有manifest.json,检查 HBuilderX 打包时是否误删/路径错位 -
"Appid not match"—— wgt 包的appid和当前运行 App 的plus.runtime.appid不一致,多见于测试时混用不同项目的 wgt - 服务端用 Nginx 或 CDN 返回 wgt 时未设置
Content-Type: application/octet-stream,某些 Android 原生 WebView 会拒绝安装;加个响应头可解决
静默更新时如何避免用户无感知导致功能异常
所谓“静默”,只是不弹窗,但下载 + 安装 + 重启全过程仍需用户处于前台(Android 后台限制严),且重启会中断当前操作。强行静默反而引发投诉。
- 推荐做法:下载完成后 toast 提示“已准备好更新”,下次冷启动时自动
restart——既减少打扰,又确保用户知情 - 不要在登录页、支付页等关键流程中触发
restart,否则用户输完密码突然闪退;可在onShow或首页mounted阶段检查并提示 - 如果真要后台下载,得用
plus.downloader替代uni.downloadFile,并监听state === 4(已完成)后再调install,但依然无法绕过重启
真正容易被忽略的是缓存一致性:wgt 更新后,localStorage、uni.getStorageSync、甚至 Vue 组件内部的 data 都不会自动清空。旧数据+新逻辑=不可预知行为,该清的缓存得在 onLaunch 里主动处理。










