Pourquoi ne pas utiliser les kits d'interface en développement mobile ?
Chez Bedev, nous utilisons activement React Native pour la création d'applications mobiles. Et pour l'un de nos clients, en début 2023, nous avons réalisé une grosse mise-à-jour avec push notifications, un chat en temps réel, nouveau design et autres fonctionnalités.
En implémentant toutes ces nouvelles fonctionnalités, nous avons rencontré quelques problèmes et je souhaite vous en parler dans cet article pour vous éviter les frustrations qui peuvent en découler.
Voici le contexte, une application mobile développée en React Native accompagnée d'une API réalisée en NestJS. Les données sont servies en GraphQL parce que, you know, GraphQL c'est la vie ! 😎
Dans le passé, nous développions nos applications mobiles sans kit d'interface. Du pur fait maison. Alors c'est évident, le fait maison ça peut prendre plus de temps à faire. Les kits d'interface, au même titre que les frameworks ou les librairies en tous genres, nous permettent de concentrer nos efforts sur l'essentiel, c'est-à-dire l'implémentation des fonctionnalités de nos applications. Elles nous évitent de se tracasser avec des configurations ou d'avoir à développer des composants de base.
NativeBase, un kit d'interface très complet qui coûte très cher
Dans l'app de notre client, nous avions opté pour NativeBase. Et c'est clair, NativeBase c'est le feu ! 🔥
Il y a tout ce qu'on attend de ce type de librairie. Certes, ils ne sont pas au niveau de MaterialUI (MUI) qui est probablement la rolls royce des kits d'interface. En revanche, MUI n'est pas disponible sur React Native (seulement ReactJS, donc pour le développement web) et je pense que NativeBase est sans doute l'un des meilleurs sur le marché des kits d'interface du développement mobile en React Native.
Mais il y a un coût indéniable. Évidemment il y a toujours un coût lorsque l'on utilise une librairie ou un framework, plus il y a de couche, plus c'est lourd. Il ne faut pas être développeur pour comprendre cela. Alors c'est souvent imperceptible mais pas dans notre cas.
Qu'est-ce qui importe le plus ? Avoir la belle vie en tant que développeur en allant plus vite ou développer une application mobile la plus performante possible ? Sans avoir de don de voyance, je connais déjà la réponse que vous vous êtes fait mentalement à cette question. Oui, je suis trop fort. 🔮
Alors oui, je suis un fervent défenseur du beau code, je ne saurais me passer de Material UI en développement web par exemple. Mais quel est l'intérêt de coder plus vite une application plus lente ? 👀
Benchmark de l'impact de NativeBase sur l'app mobile
Dans notre application mobile, nous avons un menu très simple avec des liens menant vers différents écrans de l'application. Rien de folichon.
Ce menu a été développé et ré-implémenté à différentes phases du projet. Initialement, c'était du code brut, donc pas de loop, des composants disposés en dur dans le composant Menu
. Ensuite, le menu a évolué en ScrollView
pour enfin terminer en FlatList
. Mais peu importe la façon dont il était implémenté, nous avions le même ressenti de latence ("lag" en anglais) au moment de l'ouverture du menu.
Un effet visuel très ennuyant sur lequel nous avons investigué pour trouver la cause et le supprimer. Méthodiquement, un à un, nous avons remplacé chaque composant provenant de NativeBase en composant fait maison. Un peu plus de code au final mais pas la mort non plus.
Et au fur et à mesure que nous supprimions NativeBase, nous gagnions en performance et l'effet visuel indésirable se réduisait de plus en plus jusqu'à disparaître totalement une fois NativeBase intégralement remplacé par des composants faits maison.
Nous avons décidé de mesurer le delta entre les deux implémentations pour découvrir mathématiquement la différence entre une implémentation faite maison VS une implémentation NativeBase. La mesure s'est faite simplement grâce une disposition de deux console.log()
à deux moments différents.
- Un premier
console.log()
est déclenché lorsque l'utilisateur presse le bouton pour rejoindre le menu de l'application mobile. - Un second
console.log()
est déclenché lorsque le composant du menu est monté, grâce àuseEffect
, et que l'utilisateur peut commencer à interagir avec celui-ci.
Résultat ? Cela prend 2,6x plus de temps à afficher le même menu réalisé en NativeBase qu'en React Native pur. L'affichage pour ce dernier prend 86 millisecondes contre 225 en NativeBase. Et ça pour seulement 11 éléments dans un petit menu, une liste de rien du tout ! 🤦♂️
Nous avons commencé à réaliser que les lacunes de performance relevées à différents endroits dans l'application provenaient en grande partie de NativeBase. Cela nous a notamment permis de rendre le chat plus fluide après y avoir supprimé toute référence à NativeBase.
Pourquoi cela relantit l'app mobile ?
On peut se demander pourquoi une telle différence alors que dans les faits on pense utiliser moins de code avec ces librairies. C'est vrai que utiliser un composant MenuItem
prend moins de place dans le code que d'avoir un composant View
qui contient lui même d'autres composants. Je pense que cela s'explique très certainement par la logique interne qu'il doit y avoir dans ces librairies.
Par exemple, on peut se demander le coût de la thématisation ("theeming", en anglais) où les composants sont reactifs en fonction du thème. L'on retrouve également un très grand nombre de propriétés associées à ces composants, quid de leur utilité VS leur coût lorsqu'elles ne sont même pas utilisées par le développeur ?
En conclusion, je préfère prendre plus de temps à développer une application mobile faite maison avec mes propres composants que de gaspiller des cartouches en matière de performance pour coder plus vite. De plus, commencer le plus tôt possible à réaliser vos propres composants va vous aider à construire votre kit d'interface au fil du temps.
Aujourd'hui, chez Bedev, nous possédons notre propre UI kit que nous adaptons selon les projets. Nous avons fini par gagner du temps dans nos développements mobiles tout en préservant la fluidité des apps mobiles que nous développons.
Développer une app mobile