Aller au contenu principal

Comment remplacer Differential Updater : le guide Capacitor

Découvrez comment remplacer les updaters différentiels dans vos apps Capacitor avec Capgo. Un guide de migration étape par étape couvrant les changements code, la CI et les déploiements progressifs sécurisés.

Comment remplacer Differential Updater : le guide Capacitor

Vendredi après-midi, un correctif de production est prêt, mais le mécanisme de live update de votre app Capacitor a transformé le déploiement en un jeu de devinettes. Un appareil signale le nouveau bundle, un autre conserve un ancien ensemble d'assets, et le chemin de rollback se comporte différemment selon la version arrivée en premier. L'updater semblait être une petite intégration lors de l'installation. Le remplacer s'apparente davantage à la mise en place d'un système différentiel : l'ancien assemblage doit être supprimé proprement, le nouveau doit correspondre à sa base, et chaque mesure doit être reproductible.

Cette comparaison est importante car un système de mise à jour n'est pas qu'un simple bouton de téléchargement. Il suit les versions, reconstruit les bundles, applique les limites natives et JavaScript, et décide de la marche à suivre lorsqu'un package est incomplet ou incompatible. La question pratique n'est pas seulement de savoir comment remplacer la livraison différentielle. C'est de savoir comment remplacer l'updater sans créer un second mode de défaillance pendant la migration.

Table of Contents

Reconnaître le besoin d'un nouvel updater

Le premier avertissement arrive souvent sous la forme d'un mystère opérationnel. Une release passe les tests locaux, le serveur affiche un upload réussi, et le support reçoit pourtant des rapports indiquant que les utilisateurs voient un ancien écran. L'équipe d'ingénierie compare les identifiants de bundle, les versions de build natif, l'assignation des canaux et les logs des appareils, pour découvrir que l'updater a accepté un package compilé sur une base différente de celle stockée localement.

Cela ressemble à un différentiel avec un mauvais réglage d'engrenage. Les pièces peuvent sembler compatibles, mais l'assemblage produit du bruit sous la charge. Dans une application Capacitor, l'équivalent du bruit se manifeste par un état d'assets incohérent, un échec d'extraction, des tentatives infinies ou un rollback qui ne restaure qu'une partie du bundle attendu.

Un diagnostic utile commence par les symptômes plutôt que par des suppositions :

  • Incohérence de version : Confirmez que le shell natif installé, le bundle téléchargé et les métadonnées de l'updater concordent sur leur plage de compatibilité prévue.
  • Rollback imprécis : Vérifiez si une mise à jour échouée renvoie le bundle précédent complet ou s'il reste des fichiers obsolètes.
  • Observabilité limitée : Vérifiez si vous pouvez identifier l'appareil affecté, la version du package, le canal, l'étape de l'échec et le dernier lancement réussi.
  • Ciblage non contrôlé : Recherchez les utilisateurs en production recevant des artefacts destinés à un canal beta, staging ou spécifique à un client.
  • Livraison inefficace : Vérifiez si le système envoie une archive complète alors que seuls quelques assets web ont changé. Les détails de ce compromis de conception sont expliqués dans how delta updates reduce payload size.

Un mécanicien professionnel inspectant le châssis d'un véhicule avec une lampe de poche pour diagnostiquer une éventuelle défaillance de la suspension.

Diagnostiquez avant de remplacer

Ne considérez pas chaque échec de mise à jour comme la preuve que l'updater lui-même est défectueux. Un mauvais artefact de build, une règle de canal incorrecte, un secret de signature corrompu ou un changement de compatibilité native peuvent produire le même symptôme. Capturez d'abord le chemin d'échec, incluant l'identité du package, la version de base, l'état de l'appareil et si l'app s'est lancée avec succès après l'application de la mise à jour.

Le remplacement est justifié lorsque le mécanisme ne peut plus fournir de réponses fiables ou de récupération sécurisée. Si votre équipe ne peut pas prouver quels appareils ont reçu un bundle, ne peut pas invalider rapidement une mauvaise release, ou ne peut pas garantir qu'une base manquante revient à un package complet, corriger la configuration ne fera que repousser le prochain incident.

Le principe d'ingénierie est le même que pour un train d'engrenages. Confirmez le composant défaillant avant de déposer le carter. Une migration complète de l'updater coûte plus cher au départ, mais elle vous donne un protocole propre, des règles de version explicites et une frontière de rollback testable, au lieu d'un ajustement de plus empilé sur une installation incertaine.

Retirer l'ancien mécanisme en toute sécurité

Considérez la suppression comme une procédure d'isolation contrôlée. L'objectif n'est pas de supprimer un package en espérant que le prochain build révélera ce qu'il reste. L'objectif est d'empêcher deux mécanismes de mise à jour de se disputer le même répertoire web, hook de démarrage, clé de configuration ou endpoint de livraison.

Commencez par figer la branche de migration et consigner le comportement actuel. Sauvegardez la version du plugin actif, la configuration native, les variables d'environnement, les commandes CI, les noms de canaux et l'emplacement où sont stockés les bundles téléchargés. Cet inventaire vous sera nécessaire pour distinguer les changements intentionnels des omissions accidentelles lors du premier build propre.

Établir une base de référence propre

Créez une branche jetable ou une copie de travail, puis inspectez l'arbre des dépendances et la configuration Capacitor. Identifiez le package de l'updater hérité par son nom de package réel plutôt que par une recherche générique de « update ». Examinez package.json, les lockfiles, capacitor.config.ts, les paramètres du projet iOS, les ressources Android et le code de démarrage qui appelle les méthodes download, sync, install ou rollback.

Supprimez la dépendance avec le gestionnaire de paquets utilisé par le dépôt. Par exemple, avec npm :

npm uninstall <legacy-updater-package>
npx cap sync

Utilisez la commande équivalente pour pnpm ou Yarn si votre projet les impose. Le placeholder est intentionnel. Un guide de migration ne doit pas inventer un nom de package et encourager une commande destructive sur la mauvaise dépendance.

Recherchez ensuite dans le dépôt l'ancien identifiant du plugin, les appels API, les noms d'endpoints, les clés de configuration et les event listeners. Supprimez les imports obsolètes et l'initialisation code de la couche applicative. Supprimez également les wrappers inutilisés. Laisser une abstraction locale qui appelle un updater supprimé rend le débogage ultérieur bien plus difficile, car le build peut réussir alors que le comportement au démarrage échoue.

Nettoyer les résidus natifs

Ouvrez les projets iOS et Android après la suppression de la dépendance. Supprimez les références natives que le gestionnaire de paquets n'a pas effacées, y compris les pods ajoutés manuellement, les dépendances Gradle, les entrées de manifest, les valeurs de ressources, les URL schemes, les déclarations de receivers et les hooks d'initialisation. Ne supprimez pas de fichiers simplement parce que leurs noms semblent liés. Confirmez que chaque fichier appartient exclusivement à l'ancien updater et qu'aucune configuration Capacitor partagée n'en dépend.

Lancez un refresh des dépendances natives et compilez les deux plateformes avant d'installer le remplaçant. Cela permet de distinguer les échecs de nettoyage des échecs d'intégration. Un build natif propre ne prouve pas que la migration fonctionne, mais un échec de build propre prouve que l'ancien mécanisme n'a pas été totalement neutralisé.

La même discipline s'applique aux scripts. Supprimez les anciens jobs d'upload, les variables d'endpoint, les étapes de signing, les commandes de copie d'artefacts et les notifications de release de votre CI. Vérifiez également les workflows de pull-request ainsi que les workflows de production. Un job de preview oublié peut publier un package incompatible sur un canal qui semble inoffensif jusqu'à ce qu'un testeur le reçoive.

Règle pratique : Ne migrez jamais en modifiant l'ancien updater et en ajoutant le nouveau dans le même commit. Rendez la suppression observable, effectuez un build, et seulement ensuite, introduisez le remplacement.

Avant de continuer, installez l'app nettoyée sur un appareil de test et vérifiez qu'elle ne tente plus de contacter l'ancien service. Effacez les données de l'app si nécessaire, inspectez les logs de démarrage et confirmez que l'app charge toujours ses assets web du bundle normalement. Cette base est votre échantillon de contrôle pour l'étape suivante. Pour une comparaison plus large des approches, consultez Les alternatives à CodePush pour Capacitor, Ionic et Cordova.

Installation et configuration de la nouvelle plateforme

Un updater de remplacement doit entrer dans un projet comme un protocole explicite, et non comme une bibliothèque opaque. Définissez ce qu'un bundle contient, quelles versions natives peuvent l'appliquer, comment les canaux sont mappés aux audiences, et ce que fait le client lorsque sa base stockée est indisponible. Si ces règles ne sont pas claires avant l'installation, la migration passera les tests de bon fonctionnement tout en restant risquée en production.

Ajoutez le client délibérément

Installez le nouveau package de l'updater via le gestionnaire de paquets du dépôt, puis synchronisez les projets natifs :

npm install <new-updater-package>
npx cap sync

Utilisez le nom du package et les clés de configuration documentés par le fournisseur dans le projet réel. Séparez le changement de dépendance des mises à jour Capacitor non liées afin qu'un échec de build natif ait une cause facile à identifier.

Initialisez l'updater à un moment prévisible du démarrage de l'application. Il doit connaître le build natif actuel, le canal actif, la version du bundle JS local et la politique du serveur pour la vérification des mises à jour. Évitez de disperser les appels de mise à jour sur plusieurs écrans. Un service unique doit gérer les vérifications, les téléchargements, la validation, les décisions d'installation et le reporting d'erreurs.

Le client doit distinguer une mise à jour de bundle JS d'une mise à jour de l'application native. Un bundle web ne peut pas ajouter de plugin natif, modifier les permissions de la plateforme ou supposer en toute sécurité l'existence d'un nouveau bridge natif. Encodez la compatibilité dans les métadonnées de la release et faites en sorte que l'updater rejette les packages hors de la plage native supportée.

Créer des canaux avant de publier

Configurez des flux séparés pour les tests internes, le staging et la production. Un canal est plus qu'une simple étiquette. C'est un garde-fou qui détermine quelle audience peut recevoir un package et vous offre un environnement contrôlé pour valider le démarrage, la navigation, l'authentification, le comportement hors ligne et les appels au bridge natif.

Définissez le parcours de promotion par écrit :

  1. Développement compile localement sans publier.
  2. Interne reçoit des artefacts signés pour les appareils d'ingénierie et de QA.
  3. Staging exerce des services proches de la production et la configuration de release.
  4. Production n'accepte que les artefacts ayant passé les vérifications précédentes.

Gardez l'assignation du canal en dehors du bundle de l'application dans la mesure du possible, en utilisant une configuration d'environnement gérée plutôt que des valeurs de test codées en dur. Un build de production qui pointe accidentellement vers un flux bêta est un échec du processus de release, pas une erreur utilisateur.

Protéger la frontière du bundle

Le service doit publier un bundle web complet et déterministe, même si l'optimisation du transport n'envoie ensuite que les fichiers modifiés. Générez l'artefact à partir d'un espace de travail propre, excluez les source maps ou les fichiers de développement sauf si vous avez une raison délibérée de les livrer, et enregistrez une identité de contenu pour le package résultant.

Exigez une vérification d'intégrité avant l'installation. Le client doit valider les données téléchargées, reconstruire le répertoire attendu et basculer vers celui-ci de manière atomique. Si la vérification échoue, conservez le bundle actuellement fonctionnel et signalez l'échec avec suffisamment de contexte pour le diagnostiquer.

Le modèl’OTA global, incluant le timing sécurisé des mises à jour et les limitations natives, est détaillé dans comment effectuer des mises à jour OTA.

Capture d'écran de https://capgo.app

Stockez la configuration dans le gestionnaire de secrets de la plateforme ou dans les variables CI protégées, pas dans le dépôt. Séparez l'accès en lecture pour les jobs de build des permissions administratives pouvant supprimer des releases ou modifier le ciblage de production. L'updater doit également proposer un fallback de package complet. Si l'appareil ne possède pas la version de base requise, le système ne doit pas tenter d'appliquer un patch non ancré.

Ajuster le build et les pipelines CI

La publication manuelle convient pour un test, mais elle est risquée pour un système de release. Un pipeline fiable transforme une révision de code en un artefact connu, effectue des vérifications sur cet artefact, le signe, le publie sur le canal prévu et enregistre le résultat. La même entrée doit produire la même décision de release, que le job s'exécute sur le poste d'un développeur ou sur un runner hébergé.

Compiler l'artefact dans un environnement propre

Commencez par une séquence reproductible. Installez les dépendances verrouillées, lancez le linting et les tests, compilez la couche web et générez la sortie Capacitor à partir des fichiers résultants. Ne calculez pas de différentiel par rapport au répertoire de travail d'un développeur. Comparez deux bundles immuables et versionnés produits par la CI.

Un pipeline pratique sépare les responsabilités :

  • Validation : Exécutez les tests unitaires, le type checking, le linting et un build web de production avant tout upload.
  • Compatibilité : Confirmez que les capacités natives requises par le bundle correspondent aux builds de l'application cible.
  • Packaging : Créez une archive ou un manifeste de fichiers déterministe et excluez les fichiers temporaires.
  • Signature : Signez la release avec des identifiants protégés stockés dans l'environnement CI.
  • Publication : Envoyez l'artifact vers le canal sélectionné par la branche, le tag ou l'approbation de la release.
  • Vérification : Interrogez le service de livraison et confirmez que la version publiée, le checksum et le canal concordent.

Une infographie en six étapes illustrant le processus d'amélioration continue pour optimiser le build logiciel et les pipelines CI.

Rendre l'identité de version sans ambiguïté

Utilisez un identifiant de release qui lie la révision source, la compatibilité native et le bundle publié. Ne vous reposez pas sur un label mutable comme « latest » lors du troubleshooting. L'updater doit pouvoir rapporter la version exacte installée et la version candidate exacte, tandis que le système de release doit conserver assez d'historique pour effectuer un rollback ou republier intentionnellement.

Un manifeste utile enregistre :

Champ Pourquoi c'est important
Version du bundle Identifie les assets web installés et les candidats
Compatibilité native Empêche un bundle web de supposer l'absence de code
Canal Définit l'audience cible
Version de base Ancre la reconstruction différentielle
Valeur d'intégrité Détecte la corruption ou l'altération
Statut de la release Permet les décisions de promotion, pause et rollback

La version de base est cruciale pour la livraison différentielle. La RFC 3229 décrit le modèle général : un client identifie sa représentation stockée, demande un algorithme de différence et reçoit une réponse représentant le changement plutôt que la ressource complète. L'équivalent au niveau applicatif doit calculer un patch uniquement lorsque la base connue de l'appareil est valide, et doit envoyer le bundle complet si ce n'est pas le cas.

Sécuriser le chemin de publication

Considérez le runner CI comme une machine de release privilégiée. Limitez qui peut déclencher la publication en production, gardez les éléments de signature hors des logs, faites pivoter les credentials via les contrôles de secrets de la plateforme, et empêchez les pull requests non approuvées d'accéder aux secrets de release. Les pratiques de sécurité CI/CD de DevArmor fournir un contexte utile pour renforcer les permissions, les secrets et les limites du pipeline.

Ajoutez une étape de publication en mode dry-run ou en staging avant la production. Testez l'artifact téléchargé sur un simulateur ou un appareil propre, puis testez le premier lancement, le relancement, l'interruption du téléchargement, le rejet de signature et le comportement de rollback. Gardez le job de release idempotent autant que possible. Relancer un job échoué ne devrait pas créer une collection ambiguë de packages avec des identifiants chevauchants.

Pour un modèle d'implémentation concret, utilisez le guide de configuration du pipeline CI/CD Capacitor. L'objectif n'est pas seulement d'automatiser les uploads. Il s'agit de rendre chaque release auditable, du commit source jusqu'à l'état de l'appareil.

Déploiement progressif et suivi des résultats

Un déploiement progressif est le moment où la conception de l'updater est testée sous charge. Dès le premier jour, un bundle qui semblait impeccable en staging se retrouve sur des appareils avec des bases plus anciennes, des téléchargements interrompus, un stockage faible ou des versions d'app que votre matrice QA n'avait pas couvertes. Considérez le ciblage par pourcentage comme un curseur, tandis que le véritable mécanisme de sécurité est la capacité d'arrêter la promotion et de ramener les utilisateurs vers un bundle fiable. Déployez de la même manière que vous installeriez un nouveau jeu d'engrenages différentiels : commencez par un contrôle de montage maîtrisé, guettez les problèmes, puis ouvrez-le seulement une fois que l'engrènement est prouvé stable.

Observer tout le parcours de mise à jour

Surveillez l'intégralité du parcours, pas seulement le transfert. Les appareils peuvent télécharger chaque octet et pourtant échouer lors de la vérification de la signature, de l'extraction, de l'activation ou du premier lancement après la bascule. Loguez chaque étape avec la version du bundle, la version de l'app native, le canal, la plateforme, un identifiant d'appareil respectueux de la vie privée et une catégorie d'erreur sur laquelle l'équipe peut agir.

Les signaux minimaux doivent répondre à quelques questions opérationnelles :

  • L'appareil a-t-il découvert le candidat ?
  • A-t-il reçu le bundle complet ou un patch différentiel ?
  • La validation de l'intégrité a-t-elle réussi ?
  • L'activation s'est-elle terminée ?
  • L'app a-t-elle démarré correctement ensuite ?
  • Le client est-il resté en bon état lors de sa prochaine session normale ?

Cette trace d'événements donne aux différentes équipes ce dont elles ont besoin. Le support a besoin d'une chronologie par appareil pour expliquer ce qui s'est passé sur un téléphone précis. Les responsables de release ont besoin des tendances d'adoption, d'échec et de rollback sur l'ensemble du parc. Un modèle pratique pour suivre le succès des mises à jour OTA dans les apps Capacitor correspond parfaitement à ces étapes et facilite grandement la conception du dashboard.

Une infographie professionnelle détaillant un processus en deux étapes pour déployer de nouveaux projets et surveiller leurs performances.

Use rollback as a release feature

Définissez des conditions de rollback avant de publier. Les bons déclencheurs incluent une hausse des échecs de lancement, des erreurs d'intégrité répétées, un nombre croissant d'appareils bloqués sur le candidat, ou un pattern de crash isolé à une plateforme. Conservez le dernier bundle stable sur l'appareil et rendez le retour en arrière réversible sans attendre une release sur les stores.

Le rollback nécessite aussi la conservation des preuves. Gardez les logs et les métadonnées du package ayant échoué pour que l'équipe puisse reproduire le problème, identifier la plage de compatibilité affectée et décider s'il faut restaurer l'assignation précédente ou déployer un artefact corrigé. Un rollback qui efface le symptôme pour les utilisateurs mais supprime les traces mène généralement au même échec lors de la prochaine release.

Le modèle de transport derrière la livraison différentielle existe depuis longtemps. L'encodage delta HTTP est devenu un standard web formel via la RFC 3229, publiée par l'Internet Engineering Task Force en janvier 2002, et la spécification RFC 3229 est encore utile pour une raison pratique. Un delta n'est utile que si le client possède une version de base valide et que la reconstruction du résultat coûte moins cher que l'envoi de la ressource complète.

C'est pourquoi les updaters qui connaissent l'application ont tendance à mieux fonctionner que de s'appuyer sur le comportement delta HTTP générique. Le service connaît le bundle de base, le client peut vérifier le résultat reconstruit, et l'updater peut revenir à un package complet quand le delta ne convient pas. Le choix d'ingénierie est de savoir si le protocole de livraison rend explicites la compatibilité, l'intégrité, le rollback et l'observabilité ; la réponse détermine si la livraison différentielle sert vraiment à quelque chose.

Live updates pour les apps Capacitor

Quand un bug de la couche web est en production, déployez le correctif via Capgo au lieu d'attendre des jours l'approbation des stores. Les utilisateurs reçoivent la mise à jour en arrière-plan, tandis que les changements natifs suivent le circuit de validation habituel.

Les derniers articles du blog

Capgo vous apporte les meilleures informations pour créer une application mobile vraiment professionnelle.