React Native et CodePush : déployer sans compter
Les frontières entre développement mobile et développement Web sont devenues de plus en plus poreuses. On doit ce constat en partie à React Native : base de code en JavaScript, outillage complet apportant un confort de développement rare en mobile sans pour autant laisser les performances de côté ✨.
Reste une forte contrainte quant au déploiement : même s’il s’est considérablement amélioré depuis quelques années, le délai entre la mise en production et la disponibilité d’une application reste assez long (deux jours en moyenne sur iOS ⌛️), contrairement à un projet Web, dans lequel le déploiement continu est possible et permet une plus grande agilité.
Agilité difficile à retrouver au niveau des applications mobiles : même si la mise à jour a été publiée sur le store, c’est à l’utilisateur de l’installer. Ainsi des bugs, bien qu’identifiés et corrigés, peuvent toujours subsister, engendrant inéluctablement des versions d’applications hétérogènes. Cette problématique demande donc un effort de rétro-compatibilité conséquent (problématique de versionning d’API, etc…).
Section intitulée jour-de-chance-ne-passez-pas-par-la-case-storeJour de chance : ne passez pas par la case Store 🎆
Encore une fois, l’écosystème React Native nous apporte une solution par l’intermédiaire de CodePush (développé par Microsoft). Ce dernier permet de mettre à jour vos applications sans passer par les stores et ce de façon quasi instantanée.
CodePush est un service composé de plusieurs briques :
- un outil CLI (nodeJS) ;
- un outil SaaS par l’intermédiaire du Mobile Center de Microsoft (qui a l’air prometteur) ;
- une librairie React Native (sur iOS / Android / Windows) et Cordova.
Le fonctionnement est simple :
- vous écrivez votre bout de code ;
- vous envoyez la mise à jour via le CLI ;
- l’utilisateur ouvre son app, la mise à jour se télécharge selon une stratégie définie (arrière-plan, demande explicite…) ;
- vous êtes content et l’utilisateur aussi 👩❤️👩.
En coulisses, c’est plutôt simple : une application React Native est composée d’un fichier binaire spécifique à la plateforme (Android / iOS) et d’un fichier bundle JS (généré par le packager de React Native). C’est ce dernier que CodePush va mettre à jour. Vous publiez votre nouveau bundle JS (sa totalité, il n’y a pas de gestion de “diff”) sur un serveur, le client installé dans votre application vérifie si une mise à jour est disponible, la télécharge et remplace l’ancien bundle. Si plusieurs mises à jour sont disponibles, il installera simplement la dernière.
CodePush peut donc mettre à jour uniquement le code JavaScript et certains assets de votre application. Il ne peut en aucun cas mettre à jour du code natif Android ou iOS. Concernant les assets, la liste des composants supportés est donnée ici.
Section intitulée implementation-dans-react-nativeImplémentation dans React Native 🤓
Afin de vous épargner quelques clics dans la doc, voici un récapitulatif de l’installation de CodePush au sein d’une application React Native :
1 – Installez l’outil CLI
$ yarn global add code-push-cli
2 – Créez un compte CodePush et connectez-vous
$ code-push register
Votre navigateur s’ouvre alors sur le Mobile Center, vous proposant de créer un compte. Terminez la procédure puis entrez le token donné dans votre console :
$ code-push register
Please login to Mobile Center in the browser window we've just opened.
Enter your token from the browser:
Le CLI va alors créer un fichier de config avec votre token (~/.code-push.config
).
3 – Créez vos applications sur CodePush
Il est nécessaire d’en créer une par plateforme :
$ code-push app add <app_name_ios> ios react-native
$ code-push app add <app_name_android> android react-native
CodePush va vous afficher des clés de déploiement utiles pour la phase de release.
4 – Connectez votre application React Native
Ajoutez la librairie CodePush à votre project React Native :
$ yarn add react-native-code-push
Liez votre librairie à votre projet iOS/Android en renseignant vos clés de déploiement lorsque l’on vous les demande :
$ react-native link react-native-code-push
Enfin, connectez le composant racine de votre app avec codePush()
:
import React from 'react';
import { View, Text } from 'react-native';
import codePush from "react-native-code-push";
const App = () => <View style={{ backgroundColor: "whitesmoke" }}><Text>Hello world</Text></View>;
export default codePush(App);
Et voilà ! Votre application est prête à recevoir des mises à jour ✨.
5 – Modifiez votre code
Nous allons modifier la couleur de la vue pour une couleur verte chartreuse 🍻
import React from 'react';
import { View, Text } from 'react-native';
import codePush from "react-native-code-push";
const App = () => <View style={{ backgroundColor: "chartreuse" }}><Text>Hello world</Text></View>;
export default codePush(App);
Ceci-fait, envoyez votre mise à jour sur les serveurs du Mobile Center avec le CLI :
$ code-push release-react MyApp-iOS ios
Par défaut, le déploiement se fait sur l’environnement de Staging
, vous pouvez envoyer votre release en production grâce à l’option --deploymentName
:
$ code-push release-react MyApp-iOS ios --deploymentName Production
Vos utilisateurs bénéficieront alors de votre mise à jour au lancement de l’application.
Section intitulée strategies-de-mise-a-jourStratégies de mise à jour ⛳️
Il est possible de choisir sa stratégie de mise à jour du code lors du lancement de l’application. C’est à vous de choisir celle qui s’intégrera le mieux à votre application. Le composant de CodePush est assez flexible et vous offre de nombreuses options / hooks pour implémenter votre stratégie. En voici quelques-unes :
Mise à jour en arrière plan + installation au prochain démarrage
const App = () => <Text>Hello world</Text>
export default codePush(App);
C’est la stratégie par défaut de CodePush (sans aucune configuration). CodePush va télécharger le bundle JS dès que possible et l’installer au prochain démarrage. La mise à jour est transparente mais peut mettre un peu de temps à être installée, car l’application doit être relancée.
Mise à jour en arrière plan + installation lorsque l’app revient de l’arrière plan
const App = () => <Text>Hello world</Text>
export default codePush({ checkFrequency: codePush.CheckFrequency.ON_APP_RESUME, installMode: codePush.InstallMode.ON_NEXT_RESUME })(App);
Même workflow que précédemment mis à part que la mise à jour est appliquée lorsque l’app revient de l’arrière plan (et non lorsqu’elle est arrêtée/relancée).
Mise à jour explicite avec une alerte
const App = () => <Text>Hello world</Text>
export default codePush({ updateDialog: true, installMode: codePush.InstallMode.IMMEDIATE })(App);
Lorsque la mise à jour est dispo, une alerte s’affiche proposant à l’utilisateur de l’installer (lors de la release vous pouvez ajouter l’option --mandatory
pour la rendre obligatoire). Attention cependant les conditions d’Apple pour iOS interdisent d’afficher une alerte de mise à jour, privilégiez donc ce comportement avec des applications Android.
Aussi, CodePush met à votre disposition des méthodes de cycle de vie codePushStatusDidChange()
et codePushDownloadDidProgress()
appelées à chaque étape importante :
class MyApp extends Component {
codePushStatusDidChange(status) {
switch(status) {
case codePush.SyncStatus.CHECKING_FOR_UPDATE:
console.log("Checking for updates.");
break;
case codePush.SyncStatus.DOWNLOADING_PACKAGE:
console.log("Downloading package.");
break;
case codePush.SyncStatus.INSTALLING_UPDATE:
console.log("Installing update.");
break;
case codePush.SyncStatus.UP_TO_DATE:
console.log("Up-to-date.");
break;
case codePush.SyncStatus.UPDATE_INSTALLED:
console.log("Update installed.");
break;
}
}
codePushDownloadDidProgress(progress) {
console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
}
}
MyApp = codePush(MyApp);
Cela permet d’intégrer au mieux la mise à jour : barre de progression, mise à jour de l’interface…
Section intitulée securiteSécurité 🔐
Mettre à jour votre application à la volée est une opération assez critique. Afin de garantir l’intégrité du code, CodePush propose de signer le bundle généré, la signature de celui-ci sera alors vérifiée lors de son installation côté client. Il vous faudra générer une clé asymétrique (publique/privée) :
$ openssl genrsa -out private.pem
$ openssl rsa -pubout -in private.pem -out public.pem
Vous devez alors utiliser l’option --privateKeyPath
lors de la release de votre bundle pour signer votre code. Les détails sur cette fonctionnalité se trouvent ici.
Section intitulée utilisationsUtilisations 🔎
L’utilisation de CodePush au sein de son application peut répondre à plusieurs cas :
✨ Résolution de bugs
Le cas le plus général est celui de la résolution de bugs. CodePush est l’outil parfait pour délivrer rapidement des hotfixs sur vos applications.
✨ Amélioration de l’UX/UI
Vous pouvez également mettre à jour des petits détails de vos UIs, des informations utiles à l’expérience utilisateur. Ou même changer le design de votre application un jour donné (Noël, Pâques …) si cela vous fait plaisir.
✨ A/B testing
Chose que je n’ai pas signalée, CodePush permet de déployer des releases sur un pourcentage d’utilisateurs donné. Il devient alors aisé de faire du A/B testing dans votre application. La commande suivante permet de mettre en production une release de Staging vers Production sur 42% des utilisateurs :
$ code-push promote <APP_NAME> Staging Production -r 42
✨ Easter eggs
Changer d’easter eggs toutes les semaines. 😎
Section intitulée temoignagesTémoignages 🎙
En pratique, cela améliore grandement l’agilité de tous les acteurs d’un projet :
Le développeur
« Je peux enfin hotfixer mes applications le vendredi sans devoir rejouer toute la chaîne de build. » @Thibault
L’intégrateur
« Ce décalage de 1 pixel est désormais un mauvais souvenir, j’ai pu le corriger illico presto. Mon œuvre est totale. » @Jonathan
Le e-marketeur
« Nous avons pu lancer notre nouvelle campagne disruptive sociale, le plan de tagguage dans l’app a été modifié ASAP avec un Time To Market minimal. » @Anthony
Section intitulée mot-de-la-finMot de la fin 👋
CodePush est donc un très bon outil à ajouter dans son workflow afin de gagner en agilité sur les projets mobiles pour toutes les raisons évoquées ci-dessus. On notera tout de même quelques contraintes :
- Application dépendante d’un outil SaaS ;
- Limitation des mises à jour au code JavaScript ;
- Limite des mises à jour OTA (Over The Air) avec Apple : il ne faut pas qu’elle apporte de grosses fonctionnalités. Dans ce cas, il faudra passer par une mise à jour classique via l’App Store ;
- Flou quant au coût éventuel du service. Pour l’instant il est complètement gratuit et sans limite, à voir comment le produit évolue.
Ayant ces quelques points en tête, n’hésitez pas à essayer CodePush sur vos applications React Native, je suis convaincu de la légitimité d’un tel outil.
Happy Coding ✌️
Commentaires et discussions
Nos formations sur ce sujet
Notre expertise est aussi disponible sous forme de formations professionnelles !
React Native
Développez des applications mobiles natives et cross-platform pour iOS et Android