Un auditorium aux fauteuils dorés face à une scène éclairée
Développement React Native

iOS et Android, livrés ensemble.

Des applications mobiles construites avec React Native — du code partagé entre plateformes, des composants natifs là où ça compte, et l'écosystème JavaScript derrière.

En détail

Ce qu’il faut savoir avant de commencer.

01Le choix

React Native ou Flutter, sans argumentaire de vente.

Les deux sont bons, et les deux construiront l'application. Le choix se décide en général sur des critères qui n'ont rien à voir avec des mesures de rendu.

  • Votre équipe. Si vous avez déjà des développeurs React, ou une application web React dont les types, la validation et les règles métier peuvent être partagés, React Native produit un effet cumulatif. Flutter introduit un second langage dans l'entreprise.
  • Le design. React Native s'appuie sur de vrais composants de la plateforme, ce qui convient à une application qui doit donner la sensation du système sur lequel elle tourne. Flutter dessine les siens, ce qui convient à un design très personnalisé.
  • Les dépendances. L'écosystème qui dispose déjà d'un module maintenu pour le SDK que vous n'avez pas le choix d'intégrer emporte la décision d'un coup.
  • Le web. React Native for Web permet de partager du code avec une véritable application web. C'est un avantage réel quand le même produit existe dans un navigateur.
  • Le recrutement, sur votre marché et sur le nôtre. Les deux sont répandus. Vérifiez lequel vous pouvez réellement recruter, parce que vous allez maintenir cela pendant des années.

Nous construisons avec les deux, nous n'avons donc aucune raison de vous vendre l'un plutôt que l'autre. Ce que nous ne ferons pas, c'est prétendre que la décision est évidente. Quand elle est vraiment serrée, nous le disons, et nous tranchons sur la forme de votre équipe plutôt que sur celle de la nôtre.

02Expo ou bare

Expo ou React Native bare.

C'est la première vraie décision d'un projet React Native, et la valeur par défaut a changé. Expo est aujourd'hui la manière recommandée de démarrer : il fournit le service de build, le service de mises à jour, un large ensemble de modules natifs maintenus, et un système de configuration qui génère les projets iOS et Android au lieu de les laisser comme des dossiers que quelqu'un modifie à la main.

Expo, avec des development builds

Expo Go, l'application bac à sable, n'exécute que le code natif qu'Expo embarque lui-même. Les vrais produits en sortent vite : nous construisons donc tôt un development build, votre propre binaire, avec vos propres dépendances natives, tout en gardant la boucle d'itération rapide. La configuration native s'exprime sous forme de config plugins, ce qui veut dire qu'une montée de version régénère les projets natifs au lieu d'imposer une fusion manuelle. Cette seule propriété supprime l'essentiel de la douleur historiquement associée aux mises à niveau de React Native.

Bare

Les projets natifs sont versionnés dans le dépôt et gérés à la main. C'est la bonne réponse quand vous ajoutez React Native à une application qui existe déjà, quand une dépendance demande des modifications natives qu'aucun plugin n'exprime, ou quand une équipe plateforme tient à posséder le build. Le prix à payer, c'est que chaque montée de version est à vous de fusionner.

Dans un cas comme dans l'autre, cela se décide au cadrage avec la liste des dépendances sous les yeux — et non au troisième mois.

03Brownfield

Ajouter React Native à une application existante.

Vous n'êtes pas obligé de réécrire une application pour y utiliser React Native. Une vue React Native peut être intégrée dans une application Swift ou Kotlin existante et servir une partie du produit : une nouvelle zone fonctionnelle, un parcours d'onboarding, ou la section qui change toutes les semaines quand le reste change deux fois par an.

Ce que cela coûte réellement

  • Deux systèmes de build et une seule publication. La chaîne native doit aussi produire et embarquer le bundle JavaScript.
  • La navigation qui traverse la frontière : passer un état, récupérer un résultat, et faire en sorte que le bouton retour se comporte de la même façon des deux côtés.
  • Un design system partagé, faute de quoi la couture sera visible pour les utilisateurs.
  • Le démarrage : initialiser le runtime la première fois qu'un écran React Native s'ouvre, sans que l'utilisateur regarde une vue vide.
  • Les frontières d'équipe. Quelqu'un doit être propriétaire de la jonction, sinon personne ne le sera.

Cela en vaut la peine quand une partie de l'application avance beaucoup plus vite que le reste, ou quand une équipe web peut désormais contribuer au mobile. Cela n'en vaut pas la peine pour un seul écran, et nous le disons quand c'est le cas.

04Mises à jour OTA

Les mises à jour over-the-air, et où elles s'arrêtent.

Une application React Native peut télécharger un nouveau bundle JavaScript à l'exécution : un correctif atteint donc les utilisateurs sans revue du store. C'est réellement utile : un mauvais libellé, une mise en page cassée ou un mauvais endpoint peuvent être corrigés le jour même.

Les limites, dites clairement

  • Seuls le JavaScript et les assets sont mis à jour. Ajouter ou mettre à niveau une dépendance native demande toujours un nouveau build publié sur le store.
  • Une mise à jour doit correspondre à la version de runtime du binaire sur lequel elle atterrit : les publications se suivent donc par runtime plutôt que comme un flux unique.
  • Les utilisateurs reçoivent la mise à jour au lancement suivant, pas instantanément, et les anciennes versions restent en circulation plus longtemps que prévu.
  • Les stores autorisent cela pour des correctifs et des améliorations, pas pour changer ce qu'est l'application. Livrer un produit différent en over-the-air est un problème de conformité, pas une astuce.

Utilisé correctement, c'est un filet de sécurité : déploiement par paliers, une mise à jour que l'on peut annuler, et une vraie publication sur le store pour tout ce qui est structurel. Utilisé sans discipline, cela devient un second canal de déploiement non suivi où personne ne sait quel code tourne chez un utilisateur donné. Nous gardons cette correspondance explicite, dans les notes de version et dans l'outil de suivi des plantages.

05Nouvelle architecture

La nouvelle architecture, et ce qu'elle change.

React Native a remplacé son bridge asynchrone d'origine. Fabric effectue le rendu directement à travers l'interface JavaScript, les TurboModules chargent les modules natifs à la demande au lieu de tous les charger au démarrage, la génération de code rend typée la frontière entre JavaScript et natif, et Hermes est le moteur par défaut. Les versions récentes fonctionnent ainsi par défaut.

Pour un produit construit aujourd'hui, cela se traduit surtout par un démarrage plus rapide, des interactions plus fluides sous charge, et moins d'anciens bugs de synchronisation à la frontière. Pour une application qui existe déjà, c'est une migration avec du vrai travail dedans — et le travail est rarement dans votre propre code. Il est dans les dépendances écrites pour l'ancienne architecture.

  • Chaque dépendance native doit prendre en charge la nouvelle architecture, ou être remplacée.
  • Certaines bibliothèques passent par une couche de compatibilité, qui est une solution d'attente et non une destination.
  • Les modules natifs sur mesure dont vous êtes propriétaire sont réécrits sur les nouvelles interfaces.
  • La montée de version se fait comme un lot de travail à part, avec sa propre campagne de tests, plutôt que glissée dans une version fonctionnelle.

Avant qu'un projet ne démarre, nous confrontons la liste des dépendances à ce point. Cette vérification prend une heure et elle a déjà changé notre recommandation plus d'une fois.

06Écosystème

Là où l'écosystème JavaScript aide, et là où il mord.

Là où il aide

  • Un seul langage pour le web, le mobile et souvent le backend, si bien qu'une petite équipe couvre plus de terrain sans se scinder en deux.
  • Des types et des validations partagés entre une application web et l'application mobile, pour qu'un changement d'API casse le build plutôt que l'écran d'un utilisateur.
  • Des bibliothèques matures pour ce dont toute application a besoin : navigation, listes virtualisées, formulaires, récupération et mise en cache des données, animation exécutée hors du thread JavaScript.
  • Le recrutement est plus facile, parce que les développeurs React sont nombreux et que la partie propre au mobile s'apprend.

Là où il mord

  • Une dépendance native abandonnée par son auteur devient votre problème à la prochaine version du système.
  • Les dépendances transitives font entrer du code natif que vous n'avez pas choisi et que vous embarquez désormais.
  • Les matrices de versions : React Native, le SDK Expo, les packages, Xcode et Gradle ont tous un avis les uns sur les autres.
  • Patcher un package pour le faire fonctionner est normal, et doit être consigné dans le dépôt sous peine de disparaître à la prochaine installation.

Les dépendances sont donc traitées comme des décisions. Chacune est choisie autant pour la façon dont elle est maintenue que pour ce qu'elle fait, la liste est revue avant de s'allonger, et les montées de version se font selon un calendrier plutôt que le jour où quelque chose casse. Les performances suivent la même discipline : listes virtualisées, animation hors du thread JavaScript, mémoïsation là où elle a été mesurée plutôt que saupoudrée partout, et profilage avec les outils de développement React Native et le profileur Hermes sur un vrai appareil de milieu de gamme.

07Performance et « terminé »

Les performances, et ce que « terminé » veut dire.

Performances

  • Des listes virtualisées pour tout ce qui est long, pour que l'application affiche ce qui est à l'écran et non tout ce qu'elle a jamais récupéré.
  • Animations et gestes pilotés hors du thread JavaScript, pour qu'un rendu lent ne fasse jamais saccader un balayage.
  • Des images dimensionnées et mises en cache correctement — la cause la plus fréquente de pression mémoire sur les appareils Android bon marché.
  • Moins de re-rendus : un état gardé près de l'endroit où il est utilisé, et une mémoïsation appliquée là où un profileur a montré qu'elle était nécessaire, pas partout.
  • Un démarrage mesuré sur un téléphone Android de milieu de gamme, parce que c'est de cet appareil que vient votre note sur les stores.

Terminé

  • En ligne sur les deux stores, sous vos comptes développeurs, avec vos clés de signature en votre possession.
  • Suivi des plantages et événements clés visibles par votre équipe, avec les mises à jour over-the-air rattachées aux versions, pour qu'un rapport de plantage dise de quel bundle il provient.
  • Un processus de publication reproductible et écrit : build pour le store, déploiement par paliers, et la marche à suivre pour revenir en arrière.
  • Le dépôt, la configuration de CI et les comptes tiers à votre nom.

Après cela, l'application est maintenue plutôt que terminée : une version de maintenance quelques fois par an pour les exigences des systèmes et des stores, des montées de version des dépendances selon un calendrier, et un chemin de support qui ne dépend pas de la mémoire d'une seule personne.

Questions

Les questions qui précèdent un contrat.

React Native ou Flutter ?
C'est surtout une question d'équipe, pas de préférence. Si vous avez déjà des développeurs React et TypeScript, React Native partage le langage, l'outillage et le vivier de recrutement avec votre application web, et les mêmes personnes passent de l'une à l'autre. Sans investissement React existant, et si vous voulez un moteur de rendu unique avec une interface identique partout, Flutter est en général le choix le plus tranquille.
Utilisez-vous Expo ou React Native nu ?
Expo avec TypeScript par défaut, sur la nouvelle architecture, et EAS pour les builds et les soumissions : cela supprime l'essentiel de la maintenance de la chaîne d'outils native. Quand un module natif ou une application native existante l'impose, nous passons en bare ou en prebuild, et la décision est écrite avec ses conséquences.
Nous avons déjà une application native. Peut-on y intégrer React Native ?
Oui, l'intégration brownfield fonctionne : de nouveaux écrans en React Native à l'intérieur de votre application iOS et Android existante. La mise en place est plus lourde qu'un projet neuf, car la navigation, l'état et la chaîne de build doivent tenir des deux côtés, donc nous la chiffrons comme un travail d'intégration et non comme une fonctionnalité.
Peut-on livrer des correctifs sans attendre la revue des stores ?
Les changements qui ne touchent que le JavaScript peuvent être diffusés à distance, ce qui est utile pour des correctifs et des textes. Tout ce qui touche au code natif repasse par un build et une revue, et ces mises à jour doivent rester dans les règles d'Apple et de Google : ce n'est pas un moyen de changer la nature de l'application après sa validation.
Comment se passe concrètement le travail avec une équipe à Tunis ?
Nous sommes à Tunis, en UTC+1 : la journée de travail se superpose entièrement à celle de l'Europe de l'Ouest, avec une heure d'écart au maximum pendant l'heure d'été européenne. Nous travaillons dans vos outils — votre Slack ou Teams, votre outil de tickets, votre dépôt — avec une démonstration du logiciel qui tourne à la fin de chaque sprint. Vous parlez aux personnes qui écrivent le code, pas à un commercial. Nos langues de travail sont l'anglais, le français et l'arabe.
À qui appartient le code, et si nous voulons continuer seuls ?
Tout vous appartient, et le dépôt est le vôtre dès le premier commit. La reprise comprend la documentation, la chaîne de build et de publication, les accès aux stores et une passation avec vos développeurs. Nous préférons laisser une équipe capable de maintenir l'application qu'une équipe qui en est incapable.
Contact

Un projet en tête ?

Décrivez-nous ce que vous construisez. Vous recevez une lecture honnête du périmètre, du calendrier et du coût.