Actualizaciones Manuales de Bundles de Capacitor Sin Tiendas de Aplicaciones
Las apps móviles de Capacitor requieren una publicación completa en las tiendas incluso para ajustes menores en el código JS o la configuración. Sin cambios en el código nativo, la aprobación en Google Play, RuStore, AppGallery y App Store toma días. La automatización ayuda, pero la moderación es inevitable.
La solución es actualizar el contenido del directorio dist (o build) sin reconstruir la parte nativa. El plugin @capgo/capacitor-updater permite el reemplazo de bundles over-the-air en modo manual o automático.
Cumplimiento de las Políticas de las Tiendas
Las actualizaciones de bundles JS están permitidas por todas las plataformas si se cumplen las condiciones:
- Google Play: El código interpretado (JS) está permitido siempre que no viole las políticas de abuso de recursos.
- App Store: El código descargado no cambia el propósito de la app, no crea una tienda de código y no evade la seguridad de WebView.
Estas condiciones se cumplen automáticamente para las apps híbridas de Capacitor.
Instalación y Configuración
Instala las dependencias:
npm i @capgo/capacitor-updater compare-versions
En capacitor.config.ts añade:
plugins: {
CapacitorUpdater: {
autoUpdate: false,
},
},
El modo autoUpdate: false habilita la gestión manual de actualizaciones.
Crea un AppUpdateProvider para React (adáptalo a tu framework):
const AppUpdateProvider: FC<PropsWithChildren> = ({ children }) => {
return children;
};
export default AppUpdateProvider;
Lógica de Actualización
En el provider, llama a CapacitorUpdater.notifyAppReady() dentro de los primeros 10 segundos de inicio — de lo contrario, se produce un error.
Obtén los datos del último lanzamiento vía API (GitHub o servicio interno). Compara versiones usando compare-versions.
Ejemplo de un useEffect completo:
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]);
Preparación del Bundle
Crea el archivo del bundle estrictamente usando Capgo CLI:
npx @capgo/cli bundle zip [appId] --name [myapp]
appIddecapacitor.config.ts.- Actualiza
versionenpackage.jsonantes de construir. - Sube el ZIP a un servidor HTTPS (GitHub Releases o tu propio hosting).
El enlace del archivo se pasa a CapacitorUpdater.download({ url, version }).
Después de la descarga, downloadComplete activa CapacitorUpdater.set() — el bundle se reemplaza y la app se reinicia.
Integración en la App
Provider completo:
const AppUpdateProvider: FC<PropsWithChildren> = ({ children }) => {
CapacitorUpdater.notifyAppReady();
const dispatch = useAppDispatch();
const appRelease = useAppSelector(selectAppRelease);
// useEffect how vyshe
return children;
};
En main.tsx envuelve App:
root.render(
<Provider store={store({})}>
<AppUpdateProvider>
<App />
</AppUpdateProvider>
</Provider>
);
Puntos Clave
- Las actualizaciones funcionan solo para bundles JS, sin plugins nativos.
- El bundle se archiva vía
npx @capgo/cli bundle zip— otros métodos son incorrectos. - Llamar a
notifyAppReady()es obligatorio dentro de los primeros 10 segundos de inicio. - Comparación de versiones:
compare(currentVersion, newVersion, '<'). - Capgo autoalojado — una alternativa para control total.
— Editorial Team
Aún no hay comentarios.