无需应用商店的手动 Capacitor 捆绑包更新
移动 Capacitor 应用即使只是小幅调整 JS 代码或配置,也需要完整发布到商店。没有原生代码变更的情况下,Google Play、RuStore、AppGallery 和 App Store 的审核需要数天时间。自动化能帮忙,但审核环节不可避免。
解决方案是更新 dist(或 build)目录的内容,而无需重新构建原生部分。@capgo/capacitor-updater 插件支持手动或自动模式的空中捆绑包替换。
符合商店政策
所有平台都允许 JS 捆绑包更新,前提是满足以下条件:
- Google Play:解释型代码(JS)允许,只要不违反资源滥用政策。
- App Store:下载的代码不会改变应用的核心功能,不会创建代码分发商店,并且不会绕过 WebView 安全机制。
这些条件对于 Capacitor 混合应用来说自动满足。
安装和设置
安装依赖:
npm i @capgo/capacitor-updater compare-versions
在 capacitor.config.ts 中添加:
plugins: {
CapacitorUpdater: {
autoUpdate: false,
},
},
autoUpdate: false 模式启用手动更新管理。
为 React 创建 AppUpdateProvider(根据您的框架调整):
const AppUpdateProvider: FC<PropsWithChildren> = ({ children }) => {
return children;
};
export default AppUpdateProvider;
更新逻辑
在 provider 中,启动后前 10 秒内调用 CapacitorUpdater.notifyAppReady() —— 否则会报错。
通过 API(GitHub 或内部服务)获取最新发布数据。使用 compare-versions 比较版本。
完整 useEffect 示例:
useEffect(() => {
if (appRelease === null) {
dispatch(getAppRelease({ type: ReleaseType.APP, last: true }));
} else {
const downloadBundle = async () => {
dispatch(setAppUpdating(true));
return CapacitorUpdater.download({
url: APP_BUNDLE_DOWNLOAD_LINK,
version: appRelease.version,
});
};
CapacitorUpdater.addListener('downloadComplete', async ({ bundle: downloadedBundle }) => {
try {
await CapacitorUpdater.set(downloadedBundle);
dispatch(setAppUpdating(false));
} catch (e) {
console.error(e);
dispatch(setAppUpdating(false));
}
});
if (compare(String(version), appRelease.version, '<')) downloadBundle();
return () => {
CapacitorUpdater.removeAllListeners();
App.removeAllListeners();
};
}
}, [appRelease]);
准备捆绑包
严格使用 Capgo CLI 创建捆绑包归档:
npx @capgo/cli bundle zip [appId] --name [myapp]
appId来自capacitor.config.ts。- 构建前更新
package.json中的version。 - 将 ZIP 上传到 HTTPS 服务器(GitHub Releases 或自有托管)。
归档链接传递给 CapacitorUpdater.download({ url, version })。
下载完成后,downloadComplete 事件触发 CapacitorUpdater.set() —— 捆绑包替换,应用重启。
应用集成
完整 provider:
const AppUpdateProvider: FC<PropsWithChildren> = ({ children }) => {
CapacitorUpdater.notifyAppReady();
const dispatch = useAppDispatch();
const appRelease = useAppSelector(selectAppRelease);
// useEffect 如上
return children;
};
在 main.tsx 中包装 App:
root.render(
<Provider store={store({})}>
<AppUpdateProvider>
<App />
</AppUpdateProvider>
</Provider>
);
要点
- 更新仅适用于 JS 捆绑包,不涉及原生插件。
- 捆绑包必须通过
npx @capgo/cli bundle zip归档,其他方式无效。 - 必须在启动前 10 秒内调用
notifyAppReady()。 - 版本比较:
compare(currentVersion, newVersion, '<')。 - 自托管 Capgo —— 追求完全控制的替代方案。
— Editorial Team
暂无评论。