Découverte de Flutter - CLI, DX et DevTools

par Hugo
Découverte de Flutter - CLI, DX et DevTools

Chez Premier Octet, nous développons nos applications mobiles à l’aide de React Native. Cela permet notamment d’appliquer nos connaissances sur React à la fois sur le web et sur les applications mobiles sans avoir besoin d’apprendre un nouveau framework. Néanmoins React Native possède quelques défauts, que ce soit en terme de performances (listes avec un grand nombre d’éléments par exemple), mais aussi en terme d’expérience de développement (mise à jour de la librairie, debug), bien que la release 0.60 de React Native améliore certains points (upgrade, CocoaPods par défaut, autolink notamment). Un framework créé par Google a fait son apparition en 2017 et se place aujourd’hui comme un sérieux concurrent à React Native, il s’agit de Flutter.

NB: Cet article n’a pas pour objectif de dire si Flutter est mieux ou non que React Native, mais plutôt de voir quelles sont les principales différences entre les deux.

Introduction à Flutter

Flutter est un framework qui se veut très orienté vers le design. Le but est que le développeur n’ait pas besoin de s’inquiéter des performances de son application et de se focaliser sur l’interface, là où en React Native, il est important d’optimiser au maximum son code (utilisation de PureComponent / memo aux bons endroits par exemple) en plus du design.

Flutter utilise le langage Dart, là où React Native reste sur du JavaScript. Se lancer donc dans le développement d’une application Flutter implique donc de découvrir le langage par la même occasion. Dart est un langage typé et compilé assez ressemblant au Java. Après compilation il est utilisé sous forme d’une librairie au sein de Flutter, permettant ainsi d’exécuter du code machine et d’obtenir un gain de performances comparé à React Native qui, de son côté, doit passer par un moteur JavaScript (le JavaScript Core) pour exécuter le code.

Du côté du rendu, les deux frameworks fonctionnent d’une manière totalement différente. Côté React Native, on utilise les APIs du système pour créer l’interface, par exemple UIView ou View. Du côté de Flutter, tout est directement dessiné sur un canvas Skia, tout le travail de rendu est du coup effectué en utilisant le GPU, le tout à 60 fps, tandis que le code Dart tourne grâce au CPU.

Tout comme React Native, Flutter permet de développer des modules natifs. Il faut aussi noter que Flutter ne fournit que des composants visuels, contrairement à React Native qui fournit en plus des composants visuels, des modules natifs (NetInfo, Keyboard, AsyncStorage). Il est toutefois possible d’obtenir ce genre de modules du côté de Flutter grâce aux nombreux packages disponibles sur pub.dev, l’équivalent de NPM, mais pour Dart.

L’expérience de développement

Les performances c’est bien, développer son application sans aucune frustration c’est mieux ! Nous allons aborder, pour finir cette première partie de la découverte de Flutter, avec l’expérience de développement. Debug, intégration aux IDE, toutes les infos seront là.

Le CLI

Installation

Côté React Native, l’installation du CLI est très simple, il suffit de passer par un gestionnaire de paquet type Yarn ou NPM. Néanmoins c’est un peu plus long côté Flutter. Il faut télécharger un fichier ZIP, le décompresser, le déplacer où on veut, et mettre à jour la variable PATH pour pointer sur le dossier du CLI. Il aurait été plus pratique de pouvoir obtenir le CLI directement via Homebrew par exemple. Même si certains membres de la communauté Flutter se sont attelés à la tâche, officiellement Flutter n’est pas installable via Homebrew ou quelconque gestionnaire de paquets.

Fonctionnalités

Bien qu’ils fournissent des fonctionnalités très similaires, le CLI de Flutter en fournit quelques-unes qui peuvent s’avérer utiles:

  • Pour la création d’un projet, on peut choisir le langage natif à utiliser. On pourra ainsi créer un projet utilisant Swift ou Objective-C (par défaut) sur iOS, ainsi que Kotlin ou Java (par défaut) sur Android.
  • Via la commande flutter doctor, le CLI nous informe des éventuels prérequis manquants pour lancer une application ou tout simplement des plugins manquants sur nos IDE (actuellement, la commande ne vérifie que les plugins pour Visual Studio Code et Android Studio).
  • Upgrader une application n’a jamais été aussi simple: lancer la commande flutter upgrade, et voilà ! On retrouve effectivement la même commande du côté du CLI React Native, mais il est souvent assez exhaustif de résoudre les conflits qui en découlent.

Intégration IDE

Utilisant principalement VS Code, nous n’avons testé que l’intégration sur cet IDE. Il s’agit du plugin Flutter.

Le plugin fournit un certain nombre de fonctionnalités assez intéressantes permettant de gagner du temps sur le développement:

  • Déclenchement du hot reload lors de la sauvegarde de fichiers ;
  • Debugging intégré ;
  • Ouverture très simple des DevTools sur Chrome ;
  • Ajout / échange / suppression très simple de widgets.

Quelques précisions concernant le dernier point. Un widget est l’équivalent d’un composant en React. N’ayant pas de syntaxe comme le JSX en Dart, il peut être assez fastidieux d’ajouter par exemple un widget encapsulant nos widgets déjà existants. Prenons par exemple l’image suivante :

Widget-hello-world

Au clic sur le widget Text, une petite ampoule apparaît à gauche. Au clic, plusieurs options nous sont proposées : soit d’encapsuler ce widget par un autre déjà paramétré (Container, Padding, etc), soit de l’encapsuler par un widget dont nous devrons saisir le nom. On peut aussi choisir d’extraire le widget dans une variable, une méthode ou bien dans un nouveau widget.

Widget-hello-world-options

D’autres options sont disponibles selon le widget utilisé, on pourra ainsi échanger le widget sélectionné avec le widget parent, ou tout simplement le supprimer. La démarche est simple et rapide. Ce point là est un peu plus long à faire en React et on peut facilement s’y perdre.

Le plugin Dart fournit aussi un formatage par défaut, plutôt fonctionnel dans l’ensemble, mais parfois le code sera formaté d’une manière pas forcément propre. Néanmoins, on ne s’y perd pas vraiment malgré tous les niveaux d’encapsulation que l’on peut rencontrer, le formatage rend le code clair. Le plugin ajoute même des commentaires (visibles uniquement dans l’IDE) au niveau des parenthèses fermantes, faisant en quelque sorte office de balise fermante en JSX.

Widget-comments

Les DevTools

Les DevTools de React Native ont pour avantage d’être utilisables sur n’importe quel navigateur, voir même sur une application totalement hors navigateur (react-native-debugger par exemple). En ce qui concerne Flutter, les DevTools sont utilisables uniquement sur Google Chrome. Voici les différentes fonctionnalités proposées par les DevTools de Flutter:

  • Sélection d’éléments dans l’arbre des widgets que l’on peut visualiser directement sur l’application, un peu comme si l’on activait l’inspecteur sur une application React Native, sauf qu’ici il n’est pas nécessaire de le faire. Au clic sur un élément on trouvera notamment toutes les propriétés du widget, ainsi qu’éventuellement l’état qui lui est associé ;
  • Performances de l’appli côté CPU et GPU ;
  • Logs de l’application. A noter que du côté des devtools, tous les logs sont affichés, que ce soit lorsque le Garbage Collector est exécuté ou bien qu’une animation soit executée. De manière générale les logs que vous avez explicitement défini dans votre code à l’aide de la fonction debugPrint (équivalent de console.log) seront affichés dans l’IDE, sans tous les logs inutiles.

Et… c’est tout. Malheureusement il n’est pas possible de débugger les requêtes internet depuis les devtools contrairement à react-native-debugger qui permet de visualiser les requêtes en détail comme on le ferait sur n’importe quel navigateur. Il existe des alternatives qui sont toutefois assez fastidieuses à mettre en place. On peut aussi activer les logs des requêtes mais ils ne sont pas vraiment bien fournis en terme de données, on pourra juste visualiser les données retournées ainsi que les headers de la réponse. Rien ne nous empêche néanmoins de faire tout ça à coup de debugPrint, mais il aurait été plus agréable d’avoir directement ces infos dans les DevTools.

Les messages d’erreur

C’est un point qui en a déjà frustré plus d’un sur une application React Native, souvent les messages d’erreurs ne sont pas du tout explicite, et on perd souvent du temps à en trouver la cause, même s’il est vrai qu’avec l’habitude, on arrive à trouver les causes de ces erreurs sans trop de soucis. Du côté de Flutter, on se retrouve avec des messages bien plus explicites, donnant d’une part la cause mais aussi une piste de solution pour résoudre l’erreur. Néanmoins bien qu’elles soient détaillées, il faut quand même parfois se renseigner sur internet pour obtenir une solution concrète à notre problème.

Conclusion

Nous avons trouvé l’expérience de développement bien plus agréable sur Flutter que sur React Native dans l’ensemble. Malgré un léger manque notamment au niveau des DevTools, on sent que Flutter souhaite fournir la meilleure expérience possible en permettant au développeur de se focaliser plus sur le design de son application plutôt que sur les performances et la résolution des erreurs qu’il peut rencontrer. Toutefois, nous n’avons à l’heure actuelle qu’une maigre expérience avec le framework, il est probable que certains cas particuliers soient bien plus simples à gérer côté React Native que Flutter. Il est évident qu’à l’heure actuelle, nous ne comptons pas migrer vers Flutter, mais il n’est pas impossible que dans le futur, nous réalisions une application complexe dans le but d’effectuer une comparaison plus poussée.

Continuer la discussion sur Twitter