React Native ou réelles natives ?

Depuis 2010, à chaque démarrage de projet de développement mobile, la question se pose : cross-plateforme ou technos natives ? La question est également systématique dans les salons et conférences traitant des apps mobiles.

Le développement natif consiste à développer l’application avec les langages et outils propres à chaque système d’exploitation: Android Java pour les app Android, Objective-C pour les app iPhone, C# pour les app Windows Phone. 

Le développement cross-plateforme désigne quant à lui les solutions qui permettent de développer dans un seul langage pour tous les systèmes d’exploitation, et ainsi notamment de minimiser les coûts.

Si le premier à la réputation de permettre de proposer des applications riches en termes de fonctionnalités, de qualité et de performance, il n’est pas nécessairement le choix le plus adapté à vos besoins.

Un enjeu de taille

Faire ce choix de manière pertinente a une réelle importance. Le cross plateforme fait miroiter jusqu’à 40% de réduction de coûts de développement pour des applis présentes sur les deux stores (iTunes et Play Store). On parle donc de plusieurs millions de projets, sans doute un coût de développement total d’environ 100 milliards d’euros (si tout était développé en technos natives) et annuellement environ 20% du tout en maintenances et évolutions. En lissant l’investissement du build (la création de l’app) sur 5 ans et en y ajoutant les maintenances, on n’est pas loin de 40 milliards par an. 40% de ce montant-là c’est 16 milliards d’euros … ce n’est pas rien. Pour avoir un ordre de grandeur, le marché global du gaming est évalué à quelques 120 milliards d’euro en 2018 …

Une promesse difficile à tenir ?

Les technologies candidates à porter et réaliser cette promesse de réduction de coûts, à être les championnes du cross-plateforme se sont succédées depuis 2010.

Cette succession de technos qui prospèrent puis périclitent est visible sur le graphique ci-dessous réalisé grâce à Google Trends. 

Le graphique se passe de commentaires... Comme à la boxe professionnelle, les champions se succèdent et se font détrôner par un champion plus jeune, plus performant !
En bleu : Appcelerator,
En jaune : Cordova,
En rouge : Xamarin,
En violet : Ionic 2 (basé sur cordova),
En vert : React native.

Le dernier champion en date est donc React Native. Ce framework en JavaScript est dérivé de React.js développé en open source par Facebook pour faciliter le développement d’applications web à page unique.

Il a séduit la communauté des développeurs notamment car, basé sur le langage JavaScript, il permet de constituer des équipes de développement performantes dans ce langage et qui vont pouvoir traiter les différentes parties d’une plateforme digitale (les fronts web et mobiles et les APIs).

La question du cross-plateforme versus natif semble donc se reformuler pour le moment en : React Native vs applications natives. Le retour d’expérience de la communauté des développeurs est assez partagé. Nous entendons d’un côté ceux qui assurent avoir obtenu des réductions de coûts très appréciables en utilisant React Native et nous entendons de l’autre ceux qui assurent que l’économie est un leurre et qu’on finit par la payer cher en difficultés à résoudre lorsque le projet prend de l’ampleur.

De manière assez spectaculaire l’équipe de développement d’AirBnB (contributeur champion à la plateforme React Native) a arrêté son dev sous React et repris le développement en technos natives. Les raisons évoquées font parties de celles que nous listerons plus loin dans l’article. Il y a donc bien une frontière qui partage l’ensemble des projets adaptés à un développement en React Native de ceux où il faut rester fidèle aux technologies proposées par chaque constructeur.

Les clefs de l’arbitrage

React Native est, d’une certaine façon, une couche qui vient s’intercaler entre le code source du développeur d’applications et les OS des constructeurs (iOS et Android).

Structurellement donc, un développement en React Native ne peut être ni plus performant ni plus riche en fonctionnalités qu’un développement en technos natives.

La seule question est donc de savoir si la réduction de coûts de développement est réelle et substantielle.

Les arguments pour la réduction

Le code mutualisé est bien sûr le premier argument pour l’utilisation de React Native. Plus ce code est important en proportion et plus la réduction de coût est importante.
L’abstraction par la surcouche peut éviter au développeur de prendre des actions dans son code lorsque les APIs natives des constructeurs sont modifiées.
L’utilisation du JavaScript comme langage permet de mutualiser les équipes en front web, mobile et back et d’aller chercher des développeurs dans un pool plus large que celui des spécialistes des technos mobiles natives.

Les limites de la réduction 

De la nécessité d’une partie de code natif

Il faut savoir que dans certains cas cette mutualisation n’est pas possible. Il faut recourir à des techniques permettant de traiter à part le cas de chaque plateforme. Il s’agit dans le langage de la plateforme d’utiliser les “Native Modules”. Cela se produit lorsqu’on souhaite accéder à une API du constructeur qui n’a pas été encore enveloppée (surcouchée) en React Native ou bien qu’on souhaite utiliser un ancien code ou une librairie optimisée en Objective-C ou Swift. La question est donc de savoir quelle est la proportion du code mutualisé et quelle est celle du code spécialisé.

Des experts en natif toujours indispensables

Dans la réalité, les équipes de développement ne peuvent pas se passer complètement des expertises en technologies natives. L’expérience montre que s’ils n’ont pas ces compétences, en plus des développeurs en React Native, il faut prévoir des développeurs experts du développement natif en appui.

Instabilité permanente des dépendances du code source

Pour comprendre ce point, il faut comprendre au moins succinctement la notion de dépendances en code. Cette notion est fondamentale et va de pair avec la notion de modularité, de réutilisabilité, de librairies de codes.

Pour simplifier : un développeur X crée un module M de fonctions qu’il met à la disposition de la communauté des développeurs (peu importe le mode de mise à disposition). Un autre développeur (Y) crée un module N qui utilise le module M pourvu par son confrère. On dit qu’il y a dépendance entre le module M et le module N.

Cette hiérarchie des dépendances peut aller très loin et devenir un véritable casse-tête de développeur. Plus les couches de dépendances sont importantes et plus on risque de rencontrer des difficultés. 

Pour l’anecdote, certaines difficultés provenant de modules qui dépendent de différentes versions d’un même module s’appellent collectivement “dependency hell” (ou bien l’enfer des dépendances).C’est de ce jeu de couches de dépendance que proviennent les plus grandes difficultés à tenir la promesse de réduction du coût. Le code source du développeur dépend de la plateforme React Native et des contributions de la communauté. Les contributions de la communauté dépendent de la plateforme React Native et des OS des constructeurs. La plateforme React Native dépend des OS des constructeurs. Et tout cela est en perpétuel mouvement d’évolution, le moins évoluant n’étant pas la plateforme React Native en elle-même. Pour peu que le développeur dépende d’une contribution qui dépende de la plateforme et que l’OS du constructeur soit modifié, il faut attendre que la plateforme React native soit adaptée, que la contribution soit également adaptée avant de régler le problème. Si on ne peut pas attendre, on se trouve contraint de réécrire du code natif …

UIs différenciées selon la plateforme (iOS ou Android)

Les guidelines UI d’Android et d’iOS sont distincts. Les utilisateurs ont leurs habitudes et leurs repères qu’ils aiment retrouver sur leur plateforme préférée. Si le développeur souhaite prendre en compte cette différenciation, toute la partie “Vue” du code est dé-mututalisée. Réduisant ainsi très drastiquement la partie commune du code.

Limites de performance atteintes pour les animations exigeantes 

Pour les animations graphiques exigeantes en calcul (comme le fameux effet parallaxe), l’utilisation des APIs React Native rencontrent leur limite de performance. Les animations sont saccadées et ne procurent pas à l’utilisateur une expérience aussi finies que celles obtenues en technologies natives.

Comment décider ?

On peut donc conclure que le meilleur choix dépend du type de projet.

Voici quelques questions à se poser avant de s’embarquer dans un dev en React Native. Si la réponse à une de ces questions est affirmative, pensez-y à deux fois.

  • Est-ce que mon projet a vocation à durer plus de deux ans ?
  • Est-ce qu’une UI différenciée iOS et Android est exigée ?
  • Est-ce que mon UI contient des animations graphiques complexes ?
  • Est-ce que mon application utilise des fonctions techniques très liées au hardware (exemple Bluetooth complexe, accéléromètre poussé…) ?
  • Est-ce qu’il est indispensable que tout bug entraîné par une évolution d’OS ou librairies soit immédiatement fixé (est-ce que j’ai des SLA draconiennes sur l’application) ?

Notre équipe a traduit ces questions en une calculette simple qui permet de trancher la question de manière, sinon scientifique, du moins outillée, qui ait un semblant de rigueur et qui soit cohérente d’un projet à l’autre. Cet article vous donnera, je l’espère, des pistes pour trancher et tenter d’en finir avec ce dilemme cornélien auquel nous sommes beaucoup à faire face: React Native ou Real Native ?