Capgo的版本名称起初可能会让人感到困惑: version_build 是原生应用的基准版本,而 version_name 则用于追踪设备上的 bundle。理清这两者的区别,你就能在正式发布前,准确判断设备为何能够或无法接收 OTA 更新。
我们分析了包括我们在内的 5 个 Live Update 平台的故障排除页面,发现我们的文档列出了 7 种明确的 version_build 不匹配错误代码,而其他四个平台分别只有 5、2、2 和 0 种。明确的代码意味着当出现 version_build 不匹配时,开发者无需盲目猜测。
目录
- 第 1 步:在 Capgo 中找到 version_build 和 version_name
- 第 2 步:确定 Native 基线和已下载的 bundle
- 第 3 步:检查你的 Native App 版本来源
- 第 4 步:设置并验证 Capgo 接收到的 bundle 版本
- 第 5 步:在发布更新前测试 Channel 资格
- 第 6 步:诊断版本不匹配,让发布可重复
- 常见问题
- 总结
第 1 步:在 Capgo 中找到 version_build 和 version_name
首先,请将这两者视为关于同一个 App 安装的两个不同事实。 version_build 告知 Capgo 设备上运行的是哪个 Native App 版本。 version_name 告知 Capgo 设备已下载哪个 JavaScript bundle。它们的值可能不同,这通常是符合预期的。
在 Capgo 的版本模型中,Native Build 版本是判断更新资格的基准。Capgo 会将分配给特定 Channel 的 bundle 与该 Native 基准进行对比。设备上已安装的 bundle 版本有助于识别当前的 Web code, 但它并不能取代 Channel 版本规则中的 Native 基准。
在排查问题前,请先在 Capgo 控制台的 Devices 页面查找设备并记录这两个值。然后将它们与 Channel 的目标 bundle 进行对比。这 Capgo Channel 规则 解释了如何根据以下内容检查 Channel 的目标版本 version_build.
| 值 | 其代表的含义 | 用于回答 | 典型来源 |
|---|---|---|---|
version_build |
发送至 Capgo 的 Native App 基准 | 该 Native App 是否可以接收该 Channel 的目标 bundle? | Native App 版本,或显式的 Capacitor 配置值 |
version_name |
当前已下载的 JavaScript bundle | 当前安装的是哪个 bundle 版本? | 上传时解析的 bundle 版本 |
| Channel 目标版本 | 分配给设备 Channel 的 bundle | Capgo 正在检查哪个版本的更新? | 当前 Channel 分配情况 |
在发布说明或测试报告中,请将这三个值分列显示。如果团队只写一个通用的“app version”,很容易混淆对比对象。关于更新资格,请将目标 bundle 与 version_build进行对比。对于已安装的 web code,请检查 version_name.
Capgo 的命名方式可能与 Android 的惯例不同(在 Android 中,团队通常用 “build” 表示递增的构建号)。在这里,请根据其 Capgo 角色来理解该字段,而不是看它的字面意思。养成这个小习惯可以避免发布现场的大量混乱。
步骤 2:识别 Native 基线版本与下载的 bundle
在修改版本号之前,请先识别哪个 code 是 Native 版本,哪个 code 是通过 bundle 交付的。Native App 是已安装的 iOS 或 Android 二进制文件。Bundle 则包含 Capacitor App 可以通过 OTA 更新接收的 Web 资源。
假设一个带有基线版本的 Native App 1.2.3. 后续的 Web 修复将作为 bundle 上传 1.2.4. Capgo 会检查该 channel 的目标 bundle 是否允许用于当前的 native baseline 1.2.3. 如果符合条件,设备可能会下载该 bundle。安装完成后, version_name 设备上反映的是当前的 bundle。native baseline 仍与已安装的二进制文件绑定。
当用户拥有较旧的应用商店版本但拥有较新的 Web bundle 时,这种差异就显现出来了。bundle 可以在不替换 native 二进制文件的情况下进行更改,但 OTA 更新无法添加应用中未包含的 native code。如果更改需要新的 plugin 或 native 设置,请规划一次 Native Build,而不是试图用 bundle upload 来替代。

当数值看起来不同步时,请使用此快速检查流程:
- 确认测试设备上安装的是哪个 native 二进制文件。
- 找到 Capgo 作为 native baseline 时接收到的版本值。
- 检查分配给设备 channel 的 bundle 版本。
- 分别记录已安装的 bundle 版本。
不要通过以下内容来推断 native baseline package.json 除非你的构建流程刻意将该值复制到 native version 或 Capgo 配置中。JavaScript 项目版本与应用商店安装的版本可能会出现偏差。最准确的来源是你的 App 实际发送给 Capgo 的那个值。
一旦你能区分基准版本和当前 bundle,接下来的任务就是追踪每个值的来源文件。这正是平台差异开始显现的地方。
步骤 3:检查 native app version 的来源
为了确保可靠 version_build,请找到你的 Capacitor App 所报告的 native version::Capgo 的版本文档描述了 iOS 和 Android 不同的 source keys,然后将得到的 native value 作为 OTA 对比的基准。
在 iOS 上
检查 CFBundleShortVersionString 在 App 的 Info.plist。在大多数 Xcode 项目中,该键被设置为 $(MARKETING_VERSION),因此你实际编辑的值是 target 的 Marketing Version。请务必验证构建后的 App 中的实际值,而不仅仅是查看模板或可能被构建流程覆盖的文件。
当团队更新了 Xcode 项目但未更新最终传递到 App 的值时,本地项目视图看起来可能是正确的,但安装后的二进制文件报告的值却不同。请将生成的 native app 中的版本与你的发布流程预期的值进行对比。
在 Android 上
检查 defaultConfig.versionName 在 Android 应用的 Gradle 配置中。该原生版本名称用于 Capgo 的 OTA 对比。请勿将其与 Android build code 或无关的 JavaScript package 版本混淆。对于此项检查,关键在于原生应用发送的是哪个版本名称。
统一的版本策略有助于保持两个平台的一致性,但不要假设它们已经共用同一个来源。iOS 和 Android 可能拥有不同的文件、构建步骤或发布时间。在发布检查期间对比它们的最终值,特别是当某个平台的商店发布计划有所不同时。
某些应用会显式地在 capacitor.config.ts 中通过 updater 配置的 version 值进行设置。 Capgo Semver 测试工具 将此原生基准描述为一个可以来自配置或原生应用元数据的值。如果你的应用覆盖了原生元数据,请记录这一选择,以免他人误以为商店版本是数据来源。
针对每个平台,记录下源文件、解析后的值以及包含该值的 build。这有助于在发布后更容易追踪不匹配问题,因为届时代码仓库中的版本可能已经比测试人员设备上安装的应用版本更新了。
只修改你的 build 实际读取的源文件。编辑一个过时的文件可能会让 code 审查看起来已完成,但实际打包的原生版本却并未改变。
步骤 4:设置并验证 Capgo 接收到的 bundle 版本
Bundle 版本描述的是 JavaScript 更新,而非已安装的 Native Build。Capgo 可以从以下位置获取该版本: version 字段,位于 package.json 当你未提供明确的 bundle 版本时。CLI 的 --bundle 选项可以在 upload 时设置发送的版本。
请选择一种路径并在发布流程中保持明确。如果 package.json 是来源,请在 upload 前增加该字段的版本号。如果 CI 通过 CLI 传递 bundle 版本,请让任务在发布日志中打印解析后的版本。混合使用两种路径而不加说明,会增加排查 Channel 接收到特定值原因的难度。
使用大家熟悉的语义化版本号 major.minor.patch 格式,例如 1.2.3。Capgo channel 策略会利用该版本号的组成部分,来判断目标 bundle 是否符合 Native Build 基准。 -beta.1 像 —— 这样的预发布后缀可以帮助标记特定 Channel 的 build,但请确保版本号在你的发布工具中是可解析且一致的。
在发布前请思考好版本增量:
- 对于同一发布线内的兼容性 Web 修复,请使用 patch 变更。
- 如果变更属于新的兼容特性线,请使用次版本号 (minor) 进行变更。
- 如果兼容性边界发生变化,导致旧版 Native code 可能无法支持该 bundle,请使用主版本号 (major) 进行变更。
这些标签仅作为团队规范,而非通过 OTA 增加 Native 能力的方式。版本号无法证明 bundle 对 Native App 是安全的。请务必将实际的兼容性决策与二进制文件中的 code 及依赖项保持一致。
在 upload 之前,请对比 package 版本或 CLI 值与 upload 后 bundle 显示的版本。同时检查将要发布该 bundle 的 channel。即使 bundle 命名正确,如果 upload 到错误的 channel,仍会导致错误的测试结果。
遇到无效或不一致的字符串时,应当停下来检查,而不是盲目猜测。请保留一个已知的稳定发布值,修正源码,并在正式发布前测试解析后的版本。
该 Capgo CLI 命令参考 当你将 upload 集成到脚本中时非常有用,因为 bundle 版本是 release 命令的输入参数之一。
步骤 5:在推送更新前测试 channel 资格
Channel 资格是通过对比得出的,而不是根据哪个 bundle 看起来更新来猜测的。Capgo 会将 channel 的目标 bundle 与作为以下内容发送的 Native 基准进行对比: version_build当前下载的 bundle,报告为 version_name,并不是这些 channel 规则的基准。
例如,假设已安装的 Native Build 版本为 1.2.3,而其当前的 bundle 版本为 1.2.4。如果一个 channel 指向 1.2.5,则应根据 Native Build 基准进行评估 1.2.3,而不仅仅是对比当前的 bundle 1.2.4。允许哪些目标版本取决于 channel 的更新策略。
Capgo 文档中介绍了 major 和 minor 等策略,这些策略用于限制相对于 Native Build 基准的更新。在 major 策略下,可以拦截主版本号更高的目标版本。在 minor 策略下,可以拦截改变了基准版本主版本或次版本号的目标版本。请检查配置的策略,不要盲目认为所有看起来更新的 bundle 都会被接受。

测试您计划发布的精确组合:
- 安装代表目标用户群体的 Native Build。
- 确认发送给 Capgo 的 Native Build 基准。
- 将测试设备分配到目标 channel。
- 检查 Channel 目标及其版本策略。
- 请求更新并确认设备返回的结果。
如果用户群使用了多个商店版本,请在另一个 Native Baseline 上运行相同的检查。适用于全新 Build 的 Bundle 可能会被旧版二进制拦截,而这可能是有意设置的安全规则。
对于更大范围的发布,请先从测试 Channel 或限量发布开始。扩大受众前,留意是否有非预期的准入结果。Capgo 的 Channel 模型允许团队通过发布 Channel 定向分发 Bundle;请在发布说明中明确每个 Channel 的目标和预期的 Native 版本线。
如果测试设备未更新,请在重新上传前检查其 Channel 分配和版本值。重复发布同一个 Bundle 并不能解决 Baseline 不匹配的问题。
第 6 步:诊断版本不匹配,让发布可重复
当数值与预期不符时,请按顺序排查。先确认设备上的 Native App 版本,再检查配置覆盖是否改变了 Baseline,接着对比 Capgo 收到的 Bundle 版本与 Channel 目标。这样就能把错误的源值与按设置正常工作的 Channel 规则区分开。
常见原因包括 bump 版本 package.json 在保持 Native 版本不变的同时,从不同的 release 分支构建某个平台,并测试分配到另一个 channel 的设备。另一个混淆点是将所有数字都称为“构建版本”。请务必记录清楚哪个是 Native 版本,哪个是上传的 bundle,以及当前安装的是哪个版本。
对于 CI/CD,请明确版本输入。让 pipeline 从受控源读取预期的 release 版本,然后在 upload 命令中传递该版本,或在 upload 步骤前更新 package 字段。在 job 输出中记录解析后的 Native 基准版本和 bundle 目标版本。避免依赖构建服务器无法获取的开发者本地状态。
使用发布门禁(release gate),当缺少必要版本或版本格式不符合团队规范时自动失败。然后在正式发布前,向正确的 channel 进行测试 upload。Capgo 支持基于 CLI 的部署流程,因此团队可以将 bundle upload 集成到现有的 CI/CD job 中,并保留清晰的命令日志。
不要将这些值与 Android WebView 引擎版本混淆。我们的 @capgo/capacitor-webview-version-checker plugin 会检查设备的 WebView 引擎是否过时,并可以显示 Native update prompt。这与 version_build 和 version_name是完全不同的问题,因此它永远无法替代对 Native 基准版本和 channel 目标 bundle 的检查。
从旧方案迁移时,不要试图一次性重命名所有现有值。先将旧的 native version 映射到 native baseline。然后将上传的 web release 映射到 bundle version。在引导用户使用新 channel 策略之前,先针对现有的代表性 App build 进行测试。
保留一份简短的发布记录,包含 source commit、native version、上传的 bundle version、channel 以及测试结果。如果发布需要暂停或回滚,该记录能帮助团队识别哪个 bundle 发布到了哪个环境。这也能让下次部署变得可重复,而不是依赖于某人的记忆来确认修改了哪个文件。
常见问题
Capgo 中的 version_build 和 version_name 有什么区别?
version_build 是 native app baseline,而 version_name 是当前下载的 bundle version。Capgo 在检查 channel 的目标 bundle 是否符合更新条件时,使用的是 native baseline。请在 logs 和 release notes 中将这两个值分开记录,以便区分安装的是哪个 native app 以及它对应的 web bundle。
version_name 是否控制是否允许 OTA 更新?
不,Capgo 的 channel version 策略是将目标 bundle 与 version_build(即 native baseline)进行比较。 version_name 用于识别当前下载的 bundle。如果设备没有收到更新,在修改当前的 bundle 值之前,请先检查其 baseline、channel target 以及配置的 strategy。
Capgo 从哪里获取 native version?
在 iOS 上,Capgo 读取 CFBundleShortVersionString,Xcode 通常会从中填充 MARKETING_VERSION。在 Android 上,原生版本来自 defaultConfig.versionName。在 Capacitor 配置中显式指定 updater 版本,会改变 App 发送的值,因此请验证构建后的 App。
Capgo 从哪里获取 bundle 版本?
Capgo 可以使用 version 字段,位于 package.json ,当你未显式传入 bundle 版本时。你也可以通过 CLI 的 --bundle 选项。为你的发布工作流选择一个明确的来源,然后在上传后验证 Capgo 收到的版本。
总结
使用 version_build 作为原生基准版本,以及 version_name 作为已安装的 bundle 版本。在下次发布前,请在测试设备上验证这两个值,并将 channel 目标与基准版本进行对比。这一项检查就能在版本不匹配影响更多用户前将其拦截。