Des développeurs mobiles font leurs premiers pas avec React Native

Tous les ans, on nous dit que les solutions hybrides vont remplacer le développement en natif. En tant que développeurs mobiles, ça nous a souvent fait sourire. On trouve en effet que le développement natif apporte de meilleures performances, une meilleure fluidité des applications et donc une meilleure expérience utilisateur. Mais cette année, React Native a le vent en poupe et suite aux discussions que l’on a pu avoir avec nos collègues et clients, on a voulu tester par nous même et voir si ça valait vraiment le coup.

Pour cet article, nous avons donc mis nos a priori de côté et nous nous sommes plongés dans l’écosystème JavaScript et plus particulièrement celui de React Native.

Les deux acteurs qui parlent le plus de React Native sont Facebook et AirBnB. À notre connaissance, ces derniers n’ont pas d’applications 100% React Native, mais ils embarquent par contre cette technologie dans leurs applications natives.

Après être passés dans le monde Javascript, nous avons choisi de tester la réalisation de deux applications : la première 100% React Native et la deuxième mélangeant du natif et du React Native. Voici nos retours.

1. Passage du natif au React Native

1.1 L'IDE

La première difficulté pour un développeur venant du monde natif, habitué aux IDE adaptés aux différentes plateformes comme Android Studio et Xcode, c’est de choisir parmi tous ceux qui sont disponibles pour le JavaScript, car ils sont très nombreux.

Pour vous faire gagner du temps, nous avons testé et sélectionné quelques IDE qui proposent de faire du JavaScript et du React Native. En gratuit :

  • nuclide.io qui est un package atom développé par Facebook.
  • Visual Studio Code, développé par Microsoft (il faut rajouter une extension et faire un peu de configuration pour que ce soit optimum).

En payant :

  • L’IDE Webstorm de Jetbrains qui propose beaucoup de fonctionnalités accélérant le développement comme le refactoring et la complétion de code.

1.2 Le langage

La deuxième barrière à franchir avant de commencer un projet en React Native est celle du langage. En effet, pour des développeurs habitués à des langages compilés et fortement typés comme Swift, Kotlin ou Java, passer à JavaScript est déroutant et nécessite une certaine gymnastique cérébrale. Avant d’attaquer concrètement React Native, nous avons passé un peu de temps sur les plateformes d'apprentissage en ligne comme codeschool.com ou exercism.io pour nous familiariser avec ce langage.

2. Création d’une application en React Native

2.1 L'application à créer

Nous avons choisi de réaliser notre test en développant avec React Native une application annuaire qui contient deux écrans. Le premier écran liste les employés d’une entreprise et permet de les filtrer. Le deuxième affiche le détail d’un employé et ses coordonnées pour pouvoir le contacter. Nous avions déjà développé cette application en interne en natif (en Swift pour iOS et en Kotlin pour Android) dont voici l’écran de liste :

2.2 L'architecture

Après avoir initié le projet, nous nous sommes posés la question de l’architecture à mettre en place. Dans l’équipe nous utilisons habituellement pour nos projets l’interprétation suivante de la Clean Architecture proposée par Uncle Bob :

Si vous voulez en savoir plus sur cette architecture voici un lien vers une présentation que nous avons faite à Android Makers, et un repository pour avoir une idée de l’implémentation.

Dans le cas de React (JS ou Native), Facebook préconise l’utilisation de l’architecture Flux. Les implémentations les plus connues de cette architecture étant Redux et Mobx. Pour la suite, nous avons choisi d’utiliser la plus populaire des deux, à savoir Redux. Dans nos expérimentations nous allons donc devoir oublier nos réflexes et assimiler les concepts introduits par Flux et Redux.

Dan Abramov, le co-créateur de Redux résume cette architecture dans cette issue sur le github du projet de la manière suivante :

Cette architecture, tout comme la clean architecture, peut faire peur en raison des nouveaux concepts qu’elle introduit et qu’il faudra assimiler. Cependant avec un peu de pratique, on s’y habitue rapidement.

Si vous souhaitez approfondir Redux, nous vous avons sélectionné quelques liens. Pour mieux comprendre les principes à la base de Redux, Dan Abramov les explique dans ce cours. Et si vous voulez voir un exemple de mise en place de redux dans une application React, cet article le détaille étape par étape.

2.3 Les tests unitaires

Chez OCTO, on prône le TDD, notamment pour avoir une boucle de feedback rapide sur le bon fonctionnement de l’application et nous éviter les régressions.

En natif, par exemple sur Android, on utilise JUnit pour les tests, et Mockito pour la partie Mock. Et sur iOS on prend le framework de tests unitaires XCTest fourni par Apple.

Regardons, si cela est possible avec React Native. Nous avons testé Jest, le framework de tests unitaires de Facebook, qui est présent par défaut dans le projet créé par la commande react-native init AwesomeProject.

On doit reconnaître que ce framework nous a laissé une bonne impression. Surtout dans un IDE comme WebStorm, vous pouvez lancer comme à votre habitude les tests unitaires. Faire du TDD avec React Native est donc possible et assez simple. Par ailleurs, comme le JavaScript n’est pas compilé, les tests se lancent assez rapidement et la boucle de feedback est plus rapide que dans un environnement natif.

Pour un développeur natif (iOS ou Android), il est souvent pénible de tester les vues. En effet, il faut lancer un émulateur et attendre que les tests s'exécutent. Avec React Native, pas besoin d’émulateur pour tester nos écrans, Jest propose du snapshot testing pour les composants. On pourra très facilement exécuter ces tests sur notre plateforme d’intégration continue sans forcément avoir besoin d’environnement graphique. Avec le snapshot testing, il est impossible de faire du TDD, on devra écrire le code avant le test. Si vous voulez absolument écrire les tests avant le code, vous pouvez utiliser enzyme. Avec ce framework, vous pourrez explorer le DOM, récupérer des noeuds et valider qu’ils sont corrects.

Jest fournit aussi la possibilité de créer des mocks, ce qui nous épargne une dépendance supplémentaire pour pouvoir les gérer.

Le coverage est assez facile à mettre en place également : il suffit de lancer jest avec le bon paramètre soit en ajoutant un nouveau script dans le fichier package.json ("test_with_coverage": "jest --coverage") soit en modifiant la configuration de Jest dans ce même fichier en ajoutant ("collectCoverage": true) et c’est gagné.

Vous aurez un beau petit rapport :

Selon nous et après avoir effectué tous ces tests, Jest nous semble assez complet. Et après en avoir discuté avec nos collègues qui font du JavaScript, nous nous sommes rendus compte qu’il avait aussi le vent en poupe en ce moment niveau frameworks de test dans l’écosystème JavaScript.

2.4 Le résultat

Après avoir passé la barrière du langage, mis en place notre architecture et validé qu’il était possible de faire du TDD, nous nous sommes lancés dans le développement de l’application. Et après quelques heures de travail nous sommes arrivés au résultat suivant :

Un point qui était agréable tout au long du développement est de ne pas avoir besoin de recompiler l’app pour voir le résultat de nos modifications du code. Un simple CMD+R suffit à rafraîchir l’application. Finalement c’était assez simple de recréer les deux écrans mais le plus compliqué a été de faire en sorte que ce ne soit pas trop moche. En effet, React Native utilise des styles inspirés de CSS ce que nous ne maîtrisons pas. Ce qui fait donc une nouvelle compétence à acquérir si on veut se lancer sérieusement dans le développement d’applications avec RN.

3. Intégration dans un projet existant

Dans la partie précédente nous avons vu que créer une application React Native à partir de zéro se faisait assez facilement. Dans cette partie, nous allons nous intéresser à l’intégration de React Native dans une application existante. Ce cas d’usage nous a semblé assez pertinent à tester car on y voit une opportunité de gagner du temps de développement pour des écrans avec peu de valeur ajoutée. Comme par exemple un écran “qui sommes-nous” ou “faq” qui serait développé une seule fois en React Native et intégré dans les deux applications existantes natives iOS et Android. Cette intégration pourrait aussi intéresser certaines équipes qui, pour des questions de mutualisation du développement, arrêteraient le développement en natif et développeraient les nouvelles fonctionnalités avec RN.

Nous avons donc repris l’application annuaire native existante et notre but est de la mixer avec l’application React Native que l’on vient de développer. Nous avons choisi de garder la liste de l’application native et de changer la vue de détail par celle de l’application RN. Le guide officiel de Facebook pour intégrer RN dans une app existante se trouve ici.

3.1 Comment cela se passe sur iOS ?

Version rapide : nous avons réussi mais ce n’était pas de tout repos ! Version longue : Après avoir créé un nouveau projet et ajouté le package React Native avec npm, il faut modifier le Podfile pour ajouter certaines dépendances. Jusque là ça a du sens. Mais attention, par transitivité, on se retrouve avec Boost qui contient beaucoup de librairies C++.

“Bon à la limite s’il n’y avait que ça…”

Comme tout développeur qui se respecte, nous suivons la documentation fournie par Facebook mais même ainsi, l’application ne compilait pas.

Instant pour les développeurs : Nous avons été obligés de downgrader la version de React Native afin de faire marcher l’application. Nous avons aussi dû corriger un header, pour mettre la déclaration d’import correcte. Dernier point d’attention, pour afficher une image nous avons dû ajouter la dépendance RCTImageView au Podfile qui n’était pas incluse par défaut dans la documentation.

“Et ça, c’est seulement sur iOS…”

3.2 Comment cela se passe sur Android ?

Sur Android, ce n’est pas mieux. Enfin si, si vous faites encore du Java, ça risque de mieux se passer… en tout cas au début !

Chez OCTO, cela fait environ 2 ans que nous utilisons du Kotlin, il n’est pas question de faire machine arrière d’autant plus que Google en a fait un langage officiel pour Android.

Sauf que React Native, a besoin de deux classes MainActivity.java et MainApplication.java (et oui .java !). Ce n’est pas très flexible pour une intégration avec l’existant.

Bon ce n’est pas si grave, on a réussi à contourner ce problème en créant deux classes et en les faisant hériter des classes Kotlin. Ensuite, on continue à suivre la documentation, et puis on lance react-native run-android et let’s go. Eh bien non ! On a eu droit à notre écran rouge préféré :

Donc, à ce moment là, on repasse plusieurs fois la documentation, pour voir si on n’a rien loupé. Et après on se rappelle que Google reste toujours notre meilleur ami.

Tadam ! Voici la commande qui va magiquement résoudre votre problème :

react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res

En résumé, nous avons trouvé très laborieuse l’intégration de cette techno avec de l’existant, que ce soit sur Android ou iOS. Ce qui est dommage pour une techno dont un des objectifs est d’accélérer les développements.

4. Quelques mesures

Ici, nous nous sommes intéressés seulement à la taille du binaire généré. La comparaison de la performance des applications avec et sans React Native mériterait un article entier à elle seule. L’APK de l’application native Android fait environ 9.7 Mo. Après l’intégration de la partie React Native avec seulement, un écran qui affiche une liste et un autre le détail d’un élément sélectionné, la taille de l’APK, est quasiment doublée 18.5 Mo ! Côté iOS, l’impact est moins important : l’ipa est passé de 12 à 14 Mo et l’app de 42 à 49 Mo.

Ce qui est agréable et aussi prometteur, ce que lorsque l’on passe d’un écran natif, vers un écran React Native, on ne voit pas la différence : pas de lag ou de freeze. C’est vraiment très appréciable car c’était une de nos craintes tant nous accordons une grande importance à l’expérience utilisateur.

5. Ce que nous aurions voulu tester et expérimenter

Nous aurions voulu pousser les expérimentations encore plus loin, mais l’article serait beaucoup trop long (ça fera sans doute l’objet d’un deuxième article, stay tuned) :

  • Faire un focus plus important sur les performances de React Native en comparaison avec une application native. Mais sur ce point, notre ressenti est que nous ne voyons pas tellement la différence en passant entre les deux mondes.
  • Partir d’une application React, et voir comment l’adapter au React Native.
  • Créer une application React Native, et y intégrer des composants natifs personnalisés.
  • Creuser le volet sécurité et vérifier s’il était possible de pousser la sécurisation des applications autant qu’on pourrait le faire dans un environnement natif.

Conclusion

Après avoir expérimenté React Native sur un cas plus complexe qu’un “Hello World”, nous sommes arrivés à la conclusion que cette technologie était plus prometteuse que les autres technologies hybrides qui la précédaient. Par contre comme toute technologie récente, elle évolue beaucoup ce qui peut causer certaines instabilités et la documentation peine à suivre. Attention tout de même si vous partez sur cette technologie, vos développeurs devront avoir des compétences en Javascript, CSS et mobile. Si vous ne possédez pas de développeurs JavaScript, renseignez-vous sur l’envie qu’ont vos développeurs d’utiliser ce langage mais on imagine que si vous vous intéressez à RN c’est que vous avez déjà des développeurs JS de disponibles. Selon nous, React Native peut être adapté à certains cas d’usages. On peut citer le cas de Uber qui a choisi d’utiliser cette technologie pour le développement du pendant de l’application UberEats pour les restaurateurs (https://eng.uber.com/ubereats-react-native/). N'hésitez pas à venir nous voir si vous vous posez la question pour votre projet, et nous pourrons en discuter ensemble. De notre côté, nous continuerons nos expérimentations même si selon nous ce n’est pas encore la solution miraculeuse qui nous fait dire que le développement natif est sur le point de mourir.