La maintenance de la partie "Native" des applications React Native peut être chronophage. Les mises à jour de versions majeures de React Native prennent souvent plusieurs jours et introduisent des bugs en raison d'incompatibilités avec les autres packages natifs utilisés. La mise à jour de ces derniers est également un processus fastidieux.
Expo est la solution pour simplifier le développement et la maintenance des applications React Native. Le système de prebuild d'Expo, appelé Continuous Native Generation (CNG), automatise la génération du code natif à partir de fichiers de configuration. Les config plugins intègrent des modifications natives spécifiques, tandis que l'API des Expo Modules simplifie la création de modules natifs. Expo Application Services (EAS) permet de builder et déployer des applications mobiles facilement. De plus, Expo Updates offre une solution de mise à jour over-the-air (OTA) update pour envoyer des mises à jour sans passer par les stores.
Meta recommande officiellement l'utilisation d'Expo pour les nouvelles applications React Native, comme indiqué sur le site de React Native : "To build a new app with React Native, we recommend a framework like Expo". De plus, avec la fermeture programmée d'AppCenter par Microsoft le 31 mars 2025, Expo Updates reste la seule solution viable pour les mises à jour OTA.
De nombreux projets n'ont pas démarré avec Expo car la solution n'a pas toujours été aussi complète et stable qu'aujourd'hui. Heureusement, il est possible de migrer progressivement vers Expo. D'abord en configurant une nouvelle application Expo avec l'ensemble des dépendances de l'application existante pour que le code JavaScript puisse être exécuté. Puis en mettant à jour les processus de déploiement pour utiliser EAS et Expo Updates. Enfin, en migrant vers les modules Expo pour bénéficier de modules de meilleure qualité, mieux maintenus et mis à jour automatiquement lors de la montée de version du SDK Expo.
Chez Theodo, nous avons observé des gains significatifs en termes de temps de développement et de maintenance en utilisant Expo dans nos projets. La simplification des mises à jour, l'amélioration de la productivité et la robustesse de l'écosystème Expo en font une solution incontournable pour les projets React Native. Malgré quelques défis liés à la migration et aux limitations du support de certaines plateformes, l'adoption d'Expo est une décision stratégique bénéfique à long terme.
Nous recommandons fortement de planifier la migration de votre projet vers Expo pour simplifier les mises à jour, augmenter la productivité et améliorer la maintenance des projets React Native.
Les applications universelles gagnent en popularité, permettant aux développeurs de cibler iOS, Android et le web avec une base de code commune. Cette tendance pose la question de la meilleure technologie pour gérer cette approche multi-plateforme. A Theodo nous utilisons en fonction des projets deux frameworks: Expo Router et Solito.
Comme l'indique sa documentation, Solito est à la fois :
Le principal avantage de Solito par rapport à Expo Router est qu'il permet d'utiliser les fonctionnalités avancées de Next.js. Cela permet d'activer le rendu côté serveur (SSR), d'utiliser des server components, d'améliorer la gestion des polices et des images, ainsi que d'offrir un meilleur support pour l'internationalisation.
Pour des applications pour lesquelles la performance et le SEO sont critiques, c'est un avantage incontestable. Le monorepo permet en outre d'avoir une séparation claire entre le code spécifique au web ou au mobile et le code partagé, ce qui est particulièrement intéressant si certaines features de votre application ne sont que sur le web ou que sur mobile. Un autre use case intéressant est celui où l'on a déjà une application Expo et une application NextJS et que l'on souhaite partager du code entre ces applications. On peut alors regrouper les applications sous un monorepo et partager les composants mobile progressivement.
Toutefois, l'utilisation d'un monorepo avec une application Expo et une application NextJS comporte quelques défis par rapport à une unique application sous Expo Router. Bien que cela puisse introduire une certaine complexité, comme la nécessité de maintenir deux systèmes de navigation distincts, cette approche permet également une flexibilité accrue. La création de pages reste rapide, mais pour assurer une expérience cohérente entre l'application mobile et le site web, il est important de bien synchroniser la structure des pages entre les deux routeurs. Solito facilite grandement la navigation dans le code partagé, même si l'absence de typage et d'autocomplétion pour les URLs nécessite une attention particulière pour éviter les erreurs.
Solito est une excellente option pour les projets d'application universelle pour qui le SEO et la performance sur le web sont critiques. Pour des applications qui n'auraient pas besoin de ces features, il sera plus facile et moins coûteux d'utiliser Expo Router.
Nous avons déjà parlé de Suspense lors du dernier Tech Radar, et nous avions déjà recommandé son activation.
L'intérêt majeur de Suspense avec une solution de data fetching comme React Query est la simplification des composants, dont nous n'avons plus besoin de préciser les états de chargement et le traitement des erreurs.
C'est un gain en maintenabilité, mais aussi un gain en UX puisque cela encourage le placement de loaders et d'encarts d'erreur.
Il y a toutefois un aspect sur lequel il faut être vigilant lors du passage à Suspense. Si plusieurs hooks de data fetching utilisant Suspense sont mis bout-à-bout, les tâches asynchrones s’exécuteront les unes après les autres, même si elles sont indépendantes, ce qu'on nomme communément des appels en waterfall.
La solution que nous préconisons est de répartir au maximum les hooks dans les composants les plus bas possibles de l’arbre React, pour que le composant étant suspendu soit le plus petit possible. Les composants étant suspendus en parallèle, cela permet de bien avoir des appels asynchrones en parallèle. Pour améliorer les délais avant interactivité (TTI), il est également possible de pre-fetcher les requêtes.
Récemment, l'équipe React a publié un changement cassant totalement React Query avec Suspense (tous les appels devenaient waterfall, même en appliquant l'approche ci-dessus).
Ce qu'il faut retenir, c'est que le changement a été annulé, ce qui a entraîné un report de la sortie de React 19. Cela nous rend donc particulièrement confiants dans le fait que cette façon d'utiliser Suspense est effectivement une pratique reconnue et validée par l'équipe React.
Avec tous les avantages en UX et en maintenabilité apportés par Suspense pour du data fetching (avec React Query ou d'autres librairies le supportant), nous recommandons fortement le passage à Suspense. Nous recommandons également de migrer les projets existants.
Une app étant souvent disponible à la fois sur le web et sur le mobile, il est naturel de vouloir partager du code entre ces plateformes, ce qui est possible pour la logique métier, le state d'UI et les calls API. Cependant, les composants UI ne peuvent pas être partagés par défaut.
React Native Web est une implémentation des composants et APIs React Native compatible avec React DOM.
Nous avons pu partager entre 75% et 95% du code entre des applications React web et des applications React Native en utilisant React Native Web sur plusieurs projets, et notre retour d’expérience est très positif. Les variations de la quantité de code partagé dépendent du volume du fonctionnalités spécifiques web et/ou mobile, notamment la mise en page.
Dans notre précédent radar, nous remontions des problèmes de performances et d'accessibilité. Beaucoup de travail a été fait depuis, à la fois sur react-native et react-native-web mais aussi avec des librairies de la communauté comme Tamagui et Expo Router.
React Native Web n'est pas une solution magique pour résoudre tous les problèmes de partage de code, les points restants sont davantage liés à la manière de travailler qu’à la technologie elle-même :
Nous utilisons maintenant React Native Web sur tous nos projets nécessitant le partage de code entre le web et le mobile. Cette adoption confirme notre confiance dans la technologie, que nous recommandons désormais comme une solution fiable pour développer des applications sur ces plateformes.
Le développement d’applications web nécessite de prendre en compte des contraintes qui sont en général peu connues des développeurs mobiles : taille de bundle, accès direct à n’importe quelle page via une URL, rendu côté serveur…
Pour un framework, offrir les meilleures performances vis-à-vis de ces contraintes implique de gérer directement le processus de bundling, la navigation, et éventuellement le data-fetching. C’est ce que font par exemple Next.js, Astro, et Remix.
Expo-router est un framework de navigation universel pour les apps React Native qui, grâce à son intégration aux autres outils expo, promet une expérience optimisée à la fois sur iOS/Android et sur le Web. Concrètement, expo-router propose du “filesystem-based routing” (créer un fichier dans le dossier app
définit une nouvelle route) et est une surcouche à React Navigation.
La plateforme Web est officiellement supportée avec la gestion des urls, du bundle splitting pour optimiser les performances, ou encore la possibilité d’inclure du CSS. Il s’agit du principal avantage d’expo-router.
À l’usage, la jeunesse d’Expo Router se fait encore sentir. Par exemple, le typage de la navigation est expérimental et incomplet (il ne couvre pas les search params), et l’API, en apparence simple, complique l’implémentation de certains scénarios qui ne posaient pas de problème aux développeurs maîtrisant React Navigation. Le choix d’un dossier app
dont tous les fichiers deviennent des routes oblige à maintenir 2 arbres parallèles dans la codebase, alors que d’autres frameworks reviennent en arrière sur cette contrainte voire sur l’idée même de “filesystem-based routing”.
Nous avons décidé de mettre Expo Router pour les universal apps en Trial car, il s’agit du meilleur choix pour déployer sur le Web une App React Native. Les performances ne sont néanmoins pas encore “best-in-class” (pas de server-side-rendering, pas de tree-shaking à ce jour), donc dans certains scénarios, une surcouche, par exemple avec Next.js et Solito, reste nécessaire.
Presque toutes les applications mobiles permettent à l'utilisateur d'entrer du texte et sont donc amenées à manipuler le clavier virtuel d'iOS et Android. Même dans les applications les plus populaires, des bugs ou une expérience utilisateur sub-optimale sont souvent présents autour de cette gestion du clavier.
En effet, il s'agit d'un problème plus complexe qu'il n'y parait. Et dans le cas de React Native, les différences entre les plateformes ne nous facilitent pas la tâche.
Le package react-native lui-même fournit des API limitées pour faire face à ce problème, un développeur a donc décidé de s'y attaquer et a publié React Native Keyboard Controller.
Cette bibliothèque offre une API unifiée entre iOS et Android qui inclut toutes les fonctionnalités nécessaires : ouverture/fermeture du clavier avec animation de l'UI (intégré avec reanimated), gestion des champs de texte, placement de boutons fixes au-dessus du clavier...
React Native Keyboard Controller est une bibliothèque récente et peut présenter des instabilités, mais il s'agit déjà de la solution la plus complète dans son domaine, d'où sa position dans notre cadran Trial.
Nous avons commencé à utiliser cette bibliothèque sur nos projets et encourageons les autres développeurs à faire de même.
L'un des défis majeurs lors du développement d'une application pour TV est la gestion du focus à la télécommande. Les solutions ne sont pas uniformes entre plateformes. React Native tvOS propose une implémentation, mais elle n'est pas totalement prédictible entre tvOS et AndroidTV, et n'existe pas encore pour le web. Cela complique la création d'applications universelles avec React Native.
Chez Theodo, nous avons développé React TV Space Navigation, une librairie qui réimplémente la navigation dans React sans utiliser le focus natif, assurant un comportement uniforme sur toutes les plateformes. Elle offre une API "react-friendly" avec des composants purement déclaratifs et inclut des optimisations comme la virtualisation et le défilement CSS pour améliorer les performances, notamment sur les appareils moins puissants.
Toutefois, contourner le focus natif a des limitations : le support de l'accessibilité est incomplet, et certaines fonctionnalités spécifiques, comme le "ploc" sur Android, sont absentes. Malgré ces inconvénients, nous avons déployé avec succès une application de streaming multiplateforme importante utilisant cette librairie. Cette application fait preuve d'une grande fluidité à l'utilisation.
Nous suivons l'évolution de react-native-tvos
, qui pourrait un jour rendre notre librairie obsolète. Avec un bon découpage de composants, il est facile de revenir à la gestion par défaut de react-native-tvos
, mais cela supprimerait le support du web, qui ne bénéficie d'aucune gestion de focus intégrée.
Pour l'instant, nous recommandons d'essayer notre librairie sur vos projets TV multiplateformes en ayant en tête les limites de cette solution qui vient avec certains compromis d'accessibilité et de feeling natif.
La "server-driven UI" consiste à envoyer depuis le serveur une description précise de ce qui doit être affiché à l'écran, plutôt que des données brutes. Certaines applications font appel à cette approche pour répondre à des contraintes comme la nécessité d'itérer rapidement, une forte personnalisation de l'UI, ou les limitations de taille des apps.
L'équipe React a annoncé en mars 2023 un mécanisme officiel de server-driven UI, les "React Server Components" (RSC). Ces composants peuvent être "composés" avec les "client components". React, et le framework utilisé, se chargent de gérer les interactions entre les deux mondes (créer les bons bundle javascript, réconcilier l'arbre de composants côté client, etc).
L'application mobile a alors pour seul rôle d'afficher l'UI transmise.
Les server components s'exécutant sur un serveur, ils peuvent accéder directement à des secrets, à des bases de données, ou encore au système de fichiers. Cela promet de radicalement simplifier le développement de certaines fonctionnalités. De plus, les allers-retours client-serveur sont évités, ce qui améliore les performances.
À ce jour, aucune intégration des Server Components dans un framework React Native n'existe, mais Expo travaille sur le sujet. Une implémentation React Native des Server Components devra faire face à plusieurs défis :
Nous vous invitons à surveiller comment l'écosystème des Server Components React Native évolue pour pouvoir les utiliser dès que possible, dans les cas où c'est pertinent.
Beaucoup de librairies de style ont émergé pour répondre à la popularité croissante des applications universelles. Parmi ces solutions, on retrouve Tamagui, Nativewind et Unistyles. Avec le web sont apparues de nouvelles problématiques de performance et de server-side rendering (SSR), complexifiant les solutions et rendant leur comparaison plus difficile.
Unistyles propose une API proche de celle de StyleSheet, mais avec des fonctionnalités supplémentaires : thème accessible dans le style, variants, styles dynamiques, breakpoints, accès aux insets et taille de l'écran. Le cœur de la bibliothèque est écrit en C++, offrant des performances proches de StyleSheet.
L'avantage de Unistyles est la simplicité de son API. La définition d'un thème personnalisé est simple, car la structure n'est pas imposée, contrairement à Tamagui. La proximité avec StyleSheet facilite la prise en main pour les développeurs en React Native, tandis que ceux habitués à Tailwind seraient plus familiers avec Nativewind.
La bibliothèque est compatible sur de nombreuses plateformes : web, Windows, macOS, visionOS, et TV. Cependant, le support pour le SSR n'est pas encore complet, car les styles responsives n'utilisent pas de media queries. La version 3 devrait intégrer un compiler, comme Nativewind ou Tamagui, pour générer le CSS au build time.
Unistyles est récent mais connaît un développement très actif. Le projet bénéficie de l'engagement de son principal contributeur, Jacek Pudysz, ce qui lui permet d'avancer rapidement. Cependant, cette dépendance à une seule personne peut susciter des questions quant à sa pérennité.
En résumé, Unistyles est une solution extrêmement prometteuse pour des applications universelles. Facile d'utilisation, elle offre un grand nombre de fonctionnalités pratiques. Elle manque cependant encore de maturité, notamment pour le support web, qui n'est pas encore au niveau de celui de Nativewind. Ces lacunes devraient toutefois être comblées avec la sortie de la V3.
Un SVG est un format d'image vectoriel où l’image est dessinée dynamiquement. Ce format a des propriétés intéressantes : il n'est jamais flou et peut hériter de variations de couleurs ou de formes. Cependant, dessiner dynamiquement a un coût en performance, surtout si le moteur de rendu n'est pas adapté ou si l'image est complexe.
La librairie react-native-svg
est souvent utilisée pour dessiner des SVG, en recréant chaque forme SVG en vue React, ce qui permet de les modifier ou les animer dynamiquement. Cependant, cette transformation peut être lente, particulièrement pour les icônes, qui sont souvent nombreuses sur un même écran et ralentissent le rendu.
Il existe des solutions plus adaptées pour les icônes ou les SVG statiques. Pour les icônes, on peut utiliser des polices d'icônes (icon fonts). Cela signifie convertir les SVG en lettres dans une police. La contrainte de cette solution est d'avoir un SVG mono-couleur, une caractéristique typique des icônes standards. Une méthode couramment utilisée est de recourir à IcoMoon, en combinaison avec vector-icons d'Expo.
Pour d’autres illustrations, expo-image
est une bonne alternative. Cette librairie gère les SVG et les affiche de manière plus performante. Mais il est alors impossible d'animer le SVG et de personnaliser ses couleurs (à moins d'appliquer une teinte sur tout le conteneur SVG, mais cela modifie toute l'image).
Ces alternatives couvrent une grande partie des besoins en SVG, car il est rare de devoir modifier partiellement la couleur des SVG.
Nous recommandons de ne pas utiliser react-native-svg par défaut pour tous les SVG. Il est préférable d’adopter des solutions comme les icon fonts pour les icônes, ou expo-image pour les SVG statiques afin d’améliorer les performances. Toutefois, il reste pertinent d'utiliser react-native-svg dans le cas de SVG dynamiques.
Retrouvez l'avis de nos experts sur les techniques, plateformes, outils, langages et frameworks associés aux principales technologies mobiles que nous utilisons au quotidien chez BAM : React Native, Flutter et Native.