数易学 App wgt 热更新 --- 开发笔记
1. 概述
项目采用 uni-app / 5+ App 的 wgt 资源包热更新方案:
- 不重新发整包 APK/IPA,只下发前端资源(页面、JS、静态资源等)
- App 启动时自动静默检测并安装
- 设置页提供手动「检查更新」(非静默,有交互提示)
仅 APP-PLUS 端生效,H5 / 小程序会提示「仅 App 支持热更新」。
2. 相关文件
| 文件 | 作用 |
|---|---|
src/utils/hotUpdate.js |
热更新核心逻辑(检测、下载、安装、重启) |
src/api/index.js |
apiCheckUpdate 接口封装(当前热更逻辑直接用 uni.request) |
App.vue |
onLaunch 调用 checkAppUpdate() 静默检查 |
pages/mine/privacy.vue |
「检查更新」入口,checkAppUpdate({ silent: false }) |
manifest.json |
versionName / versionCode,打 wgt 与整包版本必须对齐 |
3. 版本号配置(manifest.json)
json
"versionName": "1.0.0",
"versionCode": 100
| 字段 | 含义 |
|---|---|
versionName |
展示用版本名,wgt 必须与已安装 App 的 versionName 一致 |
versionCode |
整数版本号,wgt 的 versionCode 必须大于当前 App |
发 wgt 前:在 manifest 把 versionCode 调大 → HBuilderX 发行 原生 App-制作应用 wgt 包。
4. 后端接口
请求
ini
GET {BASE}/api/app/checkUpdate?version={versionCode}
- 免登录(启动时调用,不带 token)
version:当前 App 的versionCode(字符串)
BASE 定义在 src/api/index.js:
js
const BASE = 'http://101.37.127.125'
响应解析(parseCheckResult)
成功业务码:code === 1(或未定义 code 时走 data)
从 data 读取(兼容多种字段名):
| 含义 | 字段(任选其一) |
|---|---|
| 是否需要更新 | update / has_update / need_update |
| wgt 下载地址 | wgtUrl / wgt_url / url / download_url |
| 版本信息 | version、version_name |
需同时满足:需要更新 + 有 wgt 地址 才会下载。
API 封装(可选复用)
js
// src/api/index.js
export function apiCheckUpdate(params) {
return get(`${BASE}/api/app/checkUpdate`, params)
}
当前 hotUpdate.js 使用 uni.request 直连,未走 apiCheckUpdate。
5. 核心流程
php
App.onLaunch
└── checkAppUpdate({ silent: true }) // 默认静默
│
▼
plus.runtime.getProperty(appid) // 读当前 versionCode / versionName
│
▼
GET /api/app/checkUpdate?version=xxx
│
├── 无更新 → 仅打日志(静默)或 Toast「已是最新版本」
│
└── 有更新 + wgtUrl
│
├── silent: true → 直接 downloadAndInstall
└── silent: false → 弹窗确认后 downloadAndInstall
│
▼
uni.downloadFile(wgtUrl)
│
▼
plus.runtime.install(tempPath, { force: false })
│
▼
plus.runtime.restart() // 安装成功自动重启
6. 入口代码
6.1 启动自动检查 --- App.vue
js
import { checkAppUpdate } from './src/utils/hotUpdate'
export default {
onLaunch() {
checkAppUpdate() // 默认 silent: true,有更新直接下
}
}
6.2 手动检查 --- pages/mine/privacy.vue
js
import { checkAppUpdate } from '@/src/utils/hotUpdate.js'
function checkUpdate() {
checkAppUpdate({ silent: false })
}
silent: false 时行为:
- 显示「检查更新...」Loading
- 有新版本:弹窗「发现新版本」确认后下载
- 无更新:Toast「已是最新版本」
- 失败:弹窗 / Toast 错误信息
7. 主函数 API
js
/**
* @param {{ silent?: boolean }} options
* silent=true 启动静默(默认)
* silent=false 设置页手动检查,有确认框
*/
export function checkAppUpdate(options = {})
8. 下载与安装
js
function downloadAndInstall(wgtUrl, widgetInfo) {
uni.showLoading({ title: '正在更新...', mask: true })
uni.downloadFile({
url: wgtUrl,
success: (downloadResult) => {
// statusCode === 200 才安装
plus.runtime.install(
downloadResult.tempFilePath,
{ force: false },
() => {
uni.hideLoading()
plus.runtime.restart()
},
(e) => { /* 安装失败,formatInstallError */ }
)
}
})
}
9. 错误处理
9.1 展示策略 showUpdateError
- 文案 ≤ 18 字:
uni.showToast - 更长或强制:
uni.showModal(避免截断)
9.2 安装失败 code -1205(版本不匹配)
formatInstallError 会附加说明:
- 当前 App 的
versionName/versionCode - wgt 要求:versionName 一致 ,versionCode 必须更大
- 提示重新打 wgt
9.3 常见日志前缀
控制台搜索:[hotUpdate]
10. 条件编译
js
// #ifdef APP-PLUS
// 热更新逻辑
// #endif
// #ifndef APP-PLUS
if (!silent) {
uni.showToast({ title: '仅 App 支持热更新', icon: 'none' })
}
// #endif
11. 发版操作清单
整包(大版本 / 原生能力变更)
- 修改
manifest.json的versionName、versionCode - HBuilderX → 发行 → 原生 App-云打包 / 本地打包
- 上架应用商店
热更新 wgt(仅前端改动)
- versionName 与线上一致(如果失败增加这个值试试)
- versionCode 大于线上 App
- 发行 → 原生 App-制作应用 wgt 包
- 上传 wgt 到 OSS/CDN,后端
checkUpdate返回wgtUrl - 用户下次启动或点「检查更新」即可拉取
12. 调试建议
- 真机自定义基座 / 正式包测试(模拟器对
plus.runtime支持有限) - 看
[hotUpdate] current versionCode与接口version是否一致 - 用
silent: false在设置页手动测全流程 - wgt 安装失败先查 versionCode 是否大于当前 App
- 下载失败查 wgtUrl 是否 HTTPS、是否可公网访问
13. 依赖关系简图
flowchart LR
A[App.vue onLaunch] --> B[hotUpdate.checkAppUpdate]
C[privacy.vue 检查更新] --> B
B --> D[GET /api/app/checkUpdate]
D --> E[downloadFile]
E --> F[plus.runtime.install]
F --> G[plus.runtime.restart]
H[manifest versionCode] --> B