Skip to content

UniApp 热更新与离线包方案:wgt 升级实战 ​

结论先行:wgt 是 uni-app 的前端资源包,App 端可通过 plus.runtime.install 在线安装,实现不经过应用市场审核的资源级更新,前端 bug 修复的触达时间能从"发版 1~3 天"压缩到"几分钟";但它的能力边界必须牢记——只要动了原生层(原生插件、SDK、manifest 原生配置),就必须整包升级,热更无法覆盖。iOS 端热更受审核规则约束,不能借热更改变应用核心功能;小程序端没有热更概念,用审核加分阶段发布实现灰度。热更体系要配齐版本比较、强制更新与回滚三件套,否则一次发坏的热更包就是事故。

wgt 是什么:先划清能力边界 ​

wgt 文件可以理解为"前端资源压缩包":包含编译后的 JS、CSS、页面结构与静态资源,不含原生代码。打个比方:App 像一栋精装房,原生层是承重结构与水电管线,wgt 是墙纸、家具和软装——软装随时可以自己换,但砸墙改水电必须报建(整包发版更新)。

据此给出判定表,动手前先对号入座:

变更内容能否 wgt 热更
页面、样式、JS 逻辑、uni_modules 前端组件可以
manifest 中的应用图标、启动图(部分端)以官方文档为准,多数归入整包
新增/升级原生插件、原生 SDK、模块勾选不可以,必须整包
Android 包名/签名、iOS 证书、支付推送原生配置不可以,必须整包

小程序端(微信等)不适用 wgt 机制:小程序有平台沙箱与审核体系,更新走"提交审核 → 发布",可用分阶段发布做灰度,这本身就是官方提供的"热更替代品"。

wgt 热更全流程与代码实现 ​

标准流程四步:启动时检查版本 → 下载 wgt → 安装 → 重启生效。核心代码:

js
// App.vue onLaunch 中触发检查更新
const curVersion = plus.runtime.getProperty(plus.runtime.appid, (info) => {
  checkUpdate(info.version)
})

async function checkUpdate(localVersion) {
  const res = await uni.request({ url: 'https://api.example.com/app/latest' })
  const remote = res.data
  if (!compareVersion(remote.version, localVersion)) return // 无新版本
  if (remote.type === 'wgt') {
    // 1. 下载 wgt 到本地临时目录
    uni.downloadFile({
      url: remote.wgtUrl,
      success: (dres) => {
        // 2. 安装资源包,force=false 表示校验版本兼容
        plus.runtime.install(dres.tempFilePath, { force: false }, () => {
          // 3. 安装成功后重启应用加载新资源
          plus.runtime.restart()
        }, (err) => console.error('安装失败', err))
      }
    })
  } else {
    // 整包更新:跳转应用市场或提示下载 apk
    plus.runtime.openURL(remote.marketUrl)
  }
}

// 语义化版本比较:remote 大于 local 返回 true
function compareVersion(a, b) {
  const pa = a.split('.').map(Number), pb = b.split('.').map(Number)
  for (let i = 0; i < 3; i++) {
    if ((pa[i] || 0) !== (pb[i] || 0)) return (pa[i] || 0) > (pb[i] || 0)
  }
  return false
}

服务端版本接口返回三个关键字段:最新版本号、wgt 下载地址(放 CDN,别用业务服务器硬扛流量)、更新类型(wgt 或整包)。版本号建议全程语义化(major.minor.patch),并约定"整包大版本之下的 wgt 补丁版本"命名规则,避免出现"热更版本号跳过了用户未安装的原生版本"这类错位。

强制更新、灰度与回滚:三件套设计 ​

没有灰度与回滚的热更体系等于裸奔,三件套这样配:

  1. 三档更新策略:按版本差分档——可选更新(弹窗可跳过)、建议更新(每次启动弹窗)、强制更新(弹窗不可关闭或直接阻断使用)。强制档建议只用于安全修复与严重资损 bug,且给"强制"留一个服务端开关,误判时能远程放行。
  2. 灰度放量:wgt 下发按用户比例放量(服务端按用户 ID 哈希取模),先 5% 观察 crash 率与关键路径报错,24 小时无异常再放量到 50%、100%。App 端可接入 crash 监控对比热更前后的崩溃率曲线。
  3. 回滚预案:服务端把版本指针回拨到上一个 wgt 版本即可,用户下次启动检查更新后自动降回;因此每个 wgt 版本必须在 CDN 上保留副本,版本接口记录完整的版本链。注意回滚只能回退前端资源,若坏包已配合了服务端新接口,回滚要同步考虑接口兼容。

iOS 与小程序的合规要点 ​

两条红线提前知悉:其一,iOS 端热更在苹果审核规则下被允许的边界是"修复与优化现有功能",不能通过热更向应用注入与上架审核版本实质不同的新功能,这是行业通行共识,具体尺度以 App Store 审核指南为准;建议 iOS 端热更策略更保守,重要功能变更仍走整包审核。其二,小程序端按平台规则走:提审发布周期以平台公示为准,发布时用分阶段发布(如按 1 小时逐步放量 100%)观察用户反馈,出问题可在后台撤回版本——把"灰度意识"移植过来,比追求热更更符合平台生态。

以猫拽低代码(CatPull)为例,这类平台把发布环节产品化:可视化设计器产出的 DSL 编译到小程序、H5 与 APP 后,页面与逻辑的修改在平台内完成新版本构建,配合草稿、发布的环境分离与版本快照能力,运营侧改错内容可秒级回滚——把热更三件套(版本管理、灰度、回滚)从每个团队自建变成平台标配,正是低代码路线在发版治理上的价值。

FAQs ​

Q1:wgt 热更新了原生插件怎么办? ​

A:热更无法覆盖原生层。若必须变更原生插件或原生配置,走整包升级(Android 覆盖安装或应用市场更新,iOS 走 App Store 审核),发布前应把这类变更与 wgt 补丁错开节奏。

Q2:wgt 安装失败常见原因有哪些? ​

A:高频原因三个:下载文件不完整(CDN 缓存了半包,注意清理缓存重试)、wgt 版本与当前原生版本不匹配、存储空间不足。安装失败的兜底逻辑是引导用户走整包更新,避免卡死在旧版本。

Q3:小程序能用 wgt 热更新吗? ​

A:不能。小程序运行在平台沙箱内,资源由平台托管,更新必须走平台审核与发布流程;需要灰度时使用平台的分阶段发布能力,而不是自建热更。

延伸阅读 ​