Architecture des mises à jour OTA Capacitor : Stratégies et versions GitHub
Capacitor permet de mettre à jour le bundle JavaScript d'une application mobile sans nécessiter de révision sur Google Play ou l'App Store. L'enveloppe native reste inchangée, tandis que le code produit est remplacé via une archive ZIP. Le système utilise GitHub Releases comme source de version et @capgo/capacitor-updater pour le téléchargement. Le retour arrière automatique en cas d'échec est assuré par notifyAppReady() dans les 10 premières secondes du lancement.
Légalité et limitations
Google Play autorise les mises à jour du code interprété (JavaScript) tant que l'objectif principal de l'application n'est pas modifié. Apple permet de télécharger des bundles JS à condition que la fonctionnalité soit préservée et que les mécanismes de sécurité ne soient pas contournés. La limite est claire : les modifications de android/ ou ios/ nécessitent une publication via le store.
Installation :
npm install @capgo/capacitor-updater
npx cap sync
Dans capacitor.config.ts, désactivez la mise à jour automatique :
const config: CapacitorConfig = {
plugins: {
CapacitorUpdater: {
autoUpdate: false,
},
},
};
Construisez le bundle :
npm run build:dist
npx @capgo/cli bundle zip io.your.app --name app-bundle.zip
Nouvelle architecture : FSD et ports & adaptateurs
Le code est divisé en src/features/app-update/ (logique métier) et src/shared/api/ (adaptateurs). La fonctionnalité opère via des interfaces, indépendante de Capgo ou GitHub. Un store Zustand gère l'état, avec les composants UI isolés.
Structure :
features/app-update/model/types.ts— statuts (IDLE,CHECKING,AVAILABLE) et stratégies (NONE,NATIVE,PATCH)features/app-update/model/contracts.ts— interfaces de dépendanceshared/api/app-updater/capgo-updater-runtime.ts— wrapper sur le pluginshared/api/github/github-runtime.ts— requêtes à l'API GitHub
Stratégies de mise à jour par Semver
Détermination du type de mise à jour :
const isReleaseHasNativeUpdate = (current: SemVer, remote: SemVer): boolean =>
remote.major > current.major || remote.minor > current.minor;
const isReleaseHasPatchUpdate = (current: SemVer, remote: SemVer): boolean =>
remote.major === current.major &&
remote.minor === current.minor &&
remote.patch > current.patch;
1.1.0vs1.0.2→NATIVE(store)1.0.3vs1.0.2→PATCH(OTA)
GitHub Releases comme source unique
L'API GitHub renvoie le tag, le changelog et le lien vers app-bundle.zip. Le cas d'usage analyse les versions et sélectionne l'asset :
export const checkForAvailableUpdate = async (deps: AppUpdateDependencies): Promise<CheckResult> => {
const releaseResult = await deps.githubRuntime.getLatestReleaseInfo();
// ...
const bundleAsset = assets.find(a => a.name === 'app-bundle.zip');
// ...
};
Adaptateur pour GitHub :
export const createGithubRuntime = (): GithubRuntime => ({
getLatestReleaseInfo: async () => {
const response = await fetch(config.APP_RELEASE_URL);
const data: GithubLatestReleaseResponse = await response.json();
return { status: true, data };
},
});
Adaptateur Capgo et gestion des événements
L'interface isole la logique métier du plugin :
export const createCapgoUpdaterRuntime = (): CapgoUpdaterRuntime => ({
downloadBundle: (url, version) => CapacitorUpdater.download({ url, version }),
notifyAppReady: () => CapacitorUpdater.notifyAppReady(),
addDownloadListener: (listener) => CapacitorUpdater.addListener('download', listener),
});
Le store Zustand s'abonne à la progression :
startDownloadUpdate: async () => {
set({ status: APP_UPDATE_STATUSES.DOWNLOADING, downloadProgress: 0 });
await capgoRuntime.addDownloadListener(({ percent }) => {
set({ downloadProgress: percent });
});
const bundle = await capgoRuntime.downloadBundle(bundleDownloadUrl, remoteVersion);
},
Application : CapacitorUpdater.set(bundle) + App.minimizeApp() pour un redémarrage fluide.
Initialisation et UI
Dans main.tsx après le rendu :
await initializeUpdater();
initializeUpdater() crée les dépendances, appelle notifyAppReady() et vérifie les mises à jour. Le composant AppUpdateInfo s'affiche conditionnellement selon le statut (AVAILABLE, DOWNLOADING, DOWNLOADED).
Points clés :
- OTA uniquement pour les versions patch ; les mises à jour majeures/mineures passent par le store
notifyAppReady()dans les 10 premières secondes empêche le retour arrière- GitHub Releases combine versioning, CDN et API en un seul endroit
- L'architecture ports/adaptateurs simplifie les tests et le remplacement des fournisseurs
- Progression du téléchargement via les événements du plugin natif
— Editorial Team
Aucun commentaire pour le moment.