Un alignement des planètes sur mobile favorable à l'émergence de Flutter ?

le 04/03/2021 par Gabriel Adgeg
Tags: Software Engineering

Dans un contexte où l'hégémonie des apps mobiles est plus que jamais remise en question par les possibilités offertes par les Progressive Web Apps, voire même par des solutions no-code/low-code au rendu parfois prometteur, l’expertise mobile est obligée de se réinventer. Après avoir été attentifs aux promesses des différentes solutions cross-platform, et forts d’un premier retour d’expérience en production de 6 mois sur Flutter, nous vous proposons de réfléchir ensemble à la pertinence d’un tel framework pour réaliser un produit mobile. Après un rappel du contexte nous analyserons en quoi, techniquement mais aussi et surtout humainement, Flutter peut permettre aux développeur·se·s mobiles de se réinventer. Après avoir lu cet article, vous disposerez des meilleurs éléments de réponse quant à l’utilisation de ce framework selon vos besoins.

“Le cross-platform n’a pas d’avenir”

Combien de fois, en tant que développeur·se·s mobiles iOS et Android natif, nous sommes-nous vus challenger par la non viabilité de notre expertise ? C’est sûrement un cri du cœur, mais après avoir passé bien des années à devoir justifier que des applications développées en PhoneGap, Cordova, Ionic ou autre Xamarin ne tenaient pas leurs promesses, peut-être sommes-nous devenu·e·s trop dogmatiques.

Ces premières solutions dites “cross-platform”, “hybrides”, parfois davantage vécues comme “chimères”, sont présentes depuis que les smartphones existent. Elles répondent à un questionnement légitime de la part de toutes celles et ceux qui ont lancé des projets d’apps mobiles : pourquoi payer deux fois pour avoir une même application sur les deux plateformes mobiles iOS et Android ? Voici plusieurs éléments de réponse :

  1. iOS et Android sont deux plateformes bien différentes [1], et dès lors, ce ne sont pas les mêmes applications. En effet, pendant longtemps les designs des deux plateformes étaient différents, et il en était de même pour les composants graphiques.

    Le feed de news de l’app Facebook en 2013, à gauche sur iOS et à droite sur Android. Notez la différence de placement des onglets : en bas sur iOS et en haut sur Android.

  2. La promesse “Write Once, Run Anywhere” ne permet pas dans la grande majorité des cas de diviser les coûts par deux, ni même certaines fois de les réduire. Nos retours d’expérience nous ont montré que :

    • Le code spécifique à chaque plateforme est long à mettre en place. Il peut nécessiter d’écrire des ponts entre l’OS natif et la surcouche multi-plateforme, ce qui revient à faire des développements iOS + Android + propres au frameworks. D’un point de vue humain, il est donc nécessaire d’avoir dans son équipe les trois compétences.
    • Les projets sont dépendants de plugins de la communauté, rarement aussi bien maintenus que sur les plateformes natives. Certains ne sont même pas compatibles avec les montées de versions de frameworks (dans le cas d’Ionic par exemple, qui est un framework fondamentalement différent depuis sa version 4).
    • La scalabilité de ces projets est plus difficilement atteignable que sur les projets les projets en natif. Cela est notamment dû au fait que les plateformes et les communautés natives poussent des architectures robustes (MVVM, Clean Architecture…), ce qui est moins le cas des solutions hybrides où la bonne organisation du code et la séparation des responsabilités est souvent entièrement dépendante de l’expérience des développeur·se·s.
  3. Jusqu’à l’arrivée de React Native, le rendu de ces solutions hybrides n’est en rien comparable avec celui des applications natives iOS et Android. Ils s'appuient souvent sur un rendu web, qui est exécuté dans des composants applicatifs (WebView) moins performants que les navigateurs Safari d’iOS et Chrome d’Android Aussi peut-on légitimement se poser la question : pourquoi faire une application plutôt qu’un site responsive ?

React Native, la première solution cross-platform crédible…

Puisque ni Microsoft avec Xamarin, ni Adobe avec PhoneGap, ni Apache avec Cordova, ni Ionic (basé initialement sur Cordova) ne sont parvenus à assurer la pertinence des solutions hybrides, qui pourrait donc encore investir sur de telles solutions ? Il fallait forcément que ce soit un très gros acteur. En 2015, c’est Facebook qui a répondu présent avec React Native. La légende veut que ce framework ait été créé pour permettre aux développeur·se·s web de Facebook, parmi les plus réputés au monde, de s’occuper également des applications mobiles. Mais en quoi React Native peut-il s’avérer être une meilleure solution que celles précédemment évoquées ?

La première réponse se trouve du côté du design. Au fil des ans, Android et iOS se sont mutuellement influencés, chacun empruntant les bonnes idées de l’autre. Il en résulte des applications qui se ressemblent beaucoup plus sur les deux plateformes qu’il y a 10 ans.  Tant sur la partie UI avec les similitudes du Human Design d’Apple et du Material Design de Google, que sur l'UX avec notamment les onglets qui sont dorénavant en bas sur les deux OS, pour répondre aux contraintes des écrans toujours plus grands. Aussi, si les plateformes iOS et Android gardent évidemment toujours leurs spécificités, c’est de moins en moins le cas pour leurs rendus, et on peut dès lors considérer que l’on peut mutualiser bien plus naturellement la couche présentation.

L’accueil de l’app Youtube (réalisée en natif) en 2021, à gauche sur iOS et à droite sur Android.

Le second élément est lui technique. Contrairement aux solutions hybrides évoquées précédemment, qui en grossissant le trait “encapsulent du web dans une app”, ce n’est pas le cas de React Native. En effet, avec celui-ci les développements sont bien écrits comme du web, mais c’est le framework qui se charge de convertir cela en composants natifs iOS et Android. Le rendu s’en trouve bien plus soigné et proche des applications natives, et les économies attendues ne se font plus en sacrifiant l’expérience utilisateur.

Enfin, le dernier élément est lié à la scalabilité. Contrairement aux premiers frameworks hybrides qui laissaient le champ entièrement libre aux développeur·se·s pour organiser leur projet comme bon leur semble, React Native pousse naturellement la même architecture que celle utilisée sur la plupart des projets web en React : Redux. Cette architecture, en plus de faciliter la séparation des responsabilités applicatives, répond à une problématique commune au web et aux apps : celle du state management. En garantissant l’unicité d’un état applicatif unique, Redux facilite le débogage d’applications qui peuvent être modifiées par plusieurs sources de données à la fois (les interactions de l’utilisateur, les retours d’appels I/O asynchrones – API, base de données, la réception de push notifications…).

…quelque peu boudée par les devs iOS / Android.

Pourquoi donc ne pas s’arrêter là, et considérer que React Native est la solution universelle dès qu'il s'agit de faire un projet mobile cross-platform ? Pourquoi envisager de nouvelles solutions hybrides ? Selon nous, il y a à cet égard un facteur humain au moins aussi important que le facteur technique. Si React Native a permis à de nombreu·se·s développeur·se·s de faire des applications mobiles, le framework a davantage remporté l’adhésion de la communauté web que celle de la communauté mobile natif. D’un côté, les développeur·se·s web ont retrouvé une stack technique (JavaScript, React, Redux) et une Developer eXperience (hot reload, debug identique à du web, placement des éléments en CSS) qu’ils maîtrisent. De l’autre, nombre de développeur·se·s mobiles ont laissé d’autres essuyer les plâtres de cette énième solution hybride avant de potentiellement remettre en question le dogme de l’hégémonie du natif.

Aussi nous sommes-nous retrouvés avec des développeur·se·s web très qualifié·e·s dans leur domaine mais peu habitué·e·s aux applications mobiles. Celles-ci ont pourtant des contraintes bien différentes :

  1. Le cycle de vie d’une application mobile, avec la spécificité des déploiements sur les stores est très différent de celui d’un site web.
  2. Si les bases du design iOS et Android ont tendance à converger, encore faut-il bien les appréhender. Et puisqu’ils restent différents de ceux du web, cela n’est clairement pas une mince affaire.
  3. La problématique du hors-ligne, qui est le quotidien des développeur.se·s mobiles, est bien moins celle des développeur·se·s web. On s’en rend d’ailleurs compte avec les Service Workers qui amènent à leur tour ces considérations pour les sites web.

React Native restera donc historiquement la première solution à rendre crédible la perspective de l’hybride. Mais en ciblant un public moins enclin aux problématiques mobiles, les économies de coûts sont à mettre en balance avec le temps nécessaire pour acquérir cette expertise.

Flutter : la revanche des dev mobiles ?

Dans la suite de cet article nous développons l'idée que ce sont des considérations techniques, mais plus encore humaines, qui permettent à Flutter de tirer son épingle du jeu.

Des performances graphiques épatantes

Tout comme React Native, la première version de Flutter date de 2015. Pour autant, ce n’est que fin 2018 que ce framework produit par Google propose une version stable. Le fonctionnement de Flutter est bien différent de celui de React Native. Plutôt que de convertir du code web en natif, Flutter redessine tous les composants des applications. À la manière des moteurs de jeux vidéo comme Unity ou Unreal Engine qui permettent de n’écrire qu’une seule fois du code pour un jeu sur iOS et sur Android. Et le rendu est littéralement bluffant, encore plus avec les dernières versions du framework qui profitent d’API iOS [2] pour améliorer encore davantage les performances graphiques. Même avec l'œil d’un·e développeur·se mobile rompu·e à l’exercice, il est très difficile de distinguer le rendu d’une app écrite en Flutter de celui d’une app native. Aussi, la première condition sine qua non pour crédibiliser un framework hybride est remplie : avec Flutter, l’expérience utilisateur est conservée.

https://youtu.be/ktpDWX6jFbM

Dart, le langage du consensus

En Flutter, tout se fait en Dart. Étrange choix que ce langage pour le moins atypique pourrait-on penser ? Politiquement, le fait que ce langage soit développé par Google a forcément pesé dans la balance. Techniquement, il y a évidemment des explications à ce choix, notamment le hot reload en debug (les projets Flutter s'exécutent dans une Virtual Machine Dart au debug, mais sont bien compilés en Release, afin de permettre le rendu le plus fluide possible).

Mais ce qui nous semble le plus intéressant avec ce langage, c’est que ce n’est ni du Kotlin, ni du Swift, ni du JavaScript. Aussi, d’une certaine manière, les développeur·se·s iOS, Android et web partent tous du même point : de 0.

N’est-il pas rédhibitoire de demander à tout ce public de développeur·se·s de repartir sur un langage qu’ils ne connaissent pas ? Notre expérience nous a permis de le réaliser : pas du tout, bien au contraire. La montée en compétence est très rapide (une à deux semaines maximum), quel que soit son background (Kotlin, Swift, JS). Et finalement aucune communauté, ni Android, ni iOS, ni web n’est lésée, puisque ce n’est pas un de leur langage de prédilection qui est mis en avant.

Dans les faits, Dart ressemble à un mélange de Java et de JavaScript, typé mais avec possibilité d’inférence, qui permet de piocher dans les paradigmes de programmation objet et fonctionnelle. Les développeur·se·s en natif peuvent ressentir une certaines déception à l’idée de ne pas retrouver des fonctionnalités intéressantes de leurs langages de prédilection (les data classes de Kotlin notamment), mais les mises à jours régulières du langage tendent à montrer que celui-ci évolue dans le bon sens (la null-safety [3] est disponible en bêta depuis la version 2.12 du langage).

Une Developer eXperience de qualité

Si Dart n’apporte pas encore toutes les fonctionnalités de Kotlin ou de Swift, il n’en reste pas moins que certaines sont bien là : extensions de fonctions, opérateurs map… Mais ce qui est encore plus intéressant, c’est que certaines fonctionnalités offertes par ce langage et par Flutter sont mieux réalisées que dans les frameworks natifs.

Commençons par la Declarative UI. Ce principe inspiré du web consiste à déclarer l’interface de son app dans du code au lieu de le faire dans des fichiers XML sur Android et dans des Storyboard sur iOS. Si Android et iOS le permettent avec Jetpack Compose et Swift UI, il n’en reste pas moins que cela n’est possible que sur des versions récentes des OS (Android 5.0+, iOS 13+). Avec Flutter, la Declarative UI est accessible dès les versions d’Android 4.1 et d’iOS 8.0. Alors que les enjeux d'éco-conception numérique sont plus que jamais au cœur des réflexions, cela permet de ne pas sacrifier la rétrocompatibilité de nos apps aux profit de notre Developer eXperience [4].

Ensuite vient l’asynchronisme, dont la bonne gestion est clé dans le développement mobile afin d’assurer une parfaite fluidité de ses applications. Sur Android, après une décennie d’évolution entre les Handlers, les AsyncTasks, les Services, les Threads voire même des librairies telles que Rx, Google apporte enfin une solution clé en main avec Jetpack et ses ViewModel et LiveData. Basée sur les coroutines de Kotlin, elle permet de s’affranchir d’une grande partie de la complexité de celles-ci. Côté iOS, l’équivalent est proposé via Combine, mais il est nécessaire de cibler iOS 13+. Bien sûr, il existe des librairies tierces pour faciliter la gestion de l'asynchronisme (RxSwift, PromiseKit…), mais la référence reste GCD. Et encore une fois, il est intéressant de remarquer que l’ajout des mots clés async et await est au programme de la prochaine version de Swift [5], alors qu’avec Dart, il est d’office présent. Aussi, les développeur·se·s n’ont plus à s’occuper de la gestion des threads ou des coroutines. Ils n’ont pas même besoin de s’appuyer sur des librairies tierces pour gérer la bascule entre les background threads et le main thread. Via les mots clés async et await du langage Dart, toute la complexité de l’asynchronisme est gérée par le langage, ce qui facilite la lisibilité du code et le développement d’apps plus fluides. Et qui plus est, avec des mécanismes qui permettent de facilement les tester unitairement.

Enfin, le Hot Reload de Flutter est bien plus performant que l’Instant Run Android. Sur iOS, l’équivalent n’est disponible qu’avec Swift UI, qui nécessite les dernières versions d’iOS. Flutter permet donc sur mobile une expérience de développement bien plus proche du web, avec des modifications visibles quasi instantanément sur son terminal, là où le natif nécessite souvent un temps de compilation plus long.

Redux, disponible sur Flutter, assure la scalabilité applicative

Autre point clé, davantage que les premiers frameworks hybrides cités, Flutter propose plusieurs architectures applicatives [6] pour assurer la robustesse et la scalabilité de ses projets. Certaines sont propres aux frameworks (BLoC, Provider). Mais puisque Redux est également proposé, cette architecture nous semble davantage pertinente. Elle a l’avantage d’être déjà utilisée depuis de nombreuses années sur des projets web en production, et bénéficie d’une littérature abondante. De plus, il nous semble périlleux, pour des développeur·se·s qui doivent tout de même appréhender le langage Dart et le framework Flutter, d’avoir à appréhender des architectures pures Flutter inconnues de l’état de l’art. Aussi, grâce à cette architecture, les projets Flutter, au même titre que les projets React Native bénéficient d’un cadre clair pour assurer leur évolutivité au fil du temps.

Une communauté florissante

Flutter existe donc depuis 2015, et le moins que l’on puisse dire c’est qu’il n’a pas obtenu l’adhésion directe de la communauté Android. De manière assez surprenante, durant les workshops auxquels nous avons eu l’occasion de participer en 2017, ce sont même des Googlers, collaborateur·rice·s du framework Android, qui dissuadaient les développeur·se·s de choisir cette solution en production. Avec le recul, nous pouvons y trouver 3 justifications :

  1. Le framework n’était pas encore en version stable, et il ne possédait pas encore assez de références sérieuses en production. Ce qui n’est plus le cas dorénavant [7].
  2. Flutter était initialement perçu comme un framework permettant de réaliser des applications sur un nouvel OS de Google, Fuchsia. Dès lors, on peut légitimement se poser la question de savoir si c’était Flutter qui était remis en question, ou bien simplement la pertinence de cet OS Fuchsia au sein de Google, alors que la position d’Android était déjà dominante. En 2021, on réalise qu’on ne parle toujours pas davantage de Fuchsia, mais qu’on continue de parler de Flutter.
  3. Les préoccupations des développeur·se·s de Google ne sont pas forcément les vôtres. De fait, si vous travaillez sur une application du top 100 des app stores (Snapchat, Youtube, Whatsapp…), vous vous situez dans un environnement si concurrentiel que vous n’avez pas d’autres choix que celui du natif. Pour autant, les clients que nous accompagnons font rarement partie de ce top 100, et peuvent donc envisager des compromis. On peut se souvenir des articles d’Airbnb en 2018 qui avaient justifié le choix de ne plus utiliser React Native [8]. Ces articles ont eu une répercussion très conséquente sur la réputation du framework, alors que les problématiques d’Airbnb (leur place dans le fameux top 100, le milieu concurrentiel dans lequel ils se situent, la taille de leurs équipes) n’ont rien à voir avec celles de la majorité d’entre vous.

En 2021, les choses ont plus que changé, et l’opinion sur Flutter ne cesse d’aller en s’améliorant. Avec 114 000 “stars” sur Github [9], Flutter fait mieux que React Native (94 000 “stars” [10]). Avec 78 000 questions sur Stack Overflow [11], Flutter rivalise clairement avec les 95 000 liées à React Native [12] (à titre de comparaison, Xamarin n’en compte que 45 000 [13]). Mais plus encore, ce sont les trends de Stack Overflow [14] qui permettent de mesurer l’ascension du framework. En 2018, 0,8% des questions Stack Overflow étaient liées à React Native, et seulement 0,1% à Flutter. En 2021, ce sont 1,35% des questions qui sont liées à React Native, contre 2,2% pour Flutter. Il y a donc dans ce même laps de temps 69% de questions supplémentaires concernant React Native contre 2200% pour Flutter.

Trends Stack Overflow comparés de React Native et de Flutter.

Faut-il y voir une certaine bulle spéculative, qui pourrait éclater aussi vite qu’elle a gonflé ? Il est encore trop tôt pour y répondre, mais nous pensons que cette réputation assure au framework une pérennité certaine au moins sur les deux à trois prochaines années.

La qualité et la quantité des ressources mises à disposition par Google pour assurer la montée en compétence sur Flutter joue également un rôle clé dans son adhésion. Que l’on possède un background Android [15], iOS [16], web [17] et même React Native [18], des articles et des vidéos très bien faits détaillent étape par étape les correspondances entre nos connaissances et leurs équivalents sur Flutter. De même, la playlists Youtube Widget of the Week [19] permet en quelques minutes d’avoir une documentation précise et ludique sur chacun des composants clé de la plateforme. À ce titre, la documentation nous semble même bien meilleure que ce qu’a été celle sur Android de nombreuses années.

Enfin, le fait que les conférences Google telles la Google I/O mettent en avant Flutter [20] a naturellement permis aux développeur·se·s qui y assistaient pour d’autres raisons de s’habituer peu à peu à devoir considérer Flutter comme un acteur sérieux. Curieux paradoxe alors que le framework ne fait pas l’unanimité au sein de l’équipe Android de Google. Mais comme le dit l'adage, nul n’est prophète en son pays…

Vers la fin des apps natives ?

Alors que les designs des apps iOS et Android convergent, la promesse de la mutualisation a été historiquement rendue crédible par React Native. Mais Flutter, fort d’un rendu visuel épatant, de possibilités techniques novatrices et d’architectures assurant la scalabilité de ses projets devient de fait la seconde option à considérer. Et puisque tous les voyants sont au vert d’un point de vue technique, la pérennité de la solution sera entièrement validée par l’adhésion des développeur·se·s. Si la communauté Flutter continue de s'accroître au rythme actuel, cette compétence va devenir plus facile à trouver, et de nombreux projets mobiles pourraient dès lors être réalisés en Flutter.

À date, le choix entre React Native et Flutter dépend selon nous en priorité des compétences de vos équipes : si celles-ci ont des compétences mobiles, Flutter devrait mieux leur convenir. Si elles ont des compétences web, React Native permet de profiter davantage de leurs expertises.

Mais cela présuppose d’abord d’avoir tranché pour une solution d’application hybride. Or, au préalable il reste fondamental de se poser la question non abordée dans cet article, à savoir la nécessité d’avoir une application plutôt qu’une solution web responsive ou PWA. Et dès lors, si c’est la solution app qui est retenue, vaut-il mieux faire une application native, une application hybride voire une application en low-code/no-code (si vous êtes intéressé·e·s par le sujet, n’hésitez pas à nous l’indiquer en commentaire).

Dans cet arbitrage, React Native monopolisait jusqu’à présent l’avantage de ne pas fermer de portes entre le web et les apps mobiles. En autorisant la production de code déclinable aussi bien sur web/PWA – dans sa partie React – que sur apps mobiles – avec la couche React Native. Mais avec l’annonce hier lors de la conférence Flutter Engage du support en version stable de Flutter web [21], Google pourrait très bientôt empiéter encore davantage sur les plates-bandes de Facebook.

Les points forts et les réserves de Flutter et de React Native que nous avons identifiées.

Références

[1] Mon Android n’est pas un iPhone comme les autres, Jérôme Van Der Linden, blog OCTO, 12/2013

[2] Announcing Flutter 1.17, Chris Sells, Medium, 05/2020

[3] Null Safety in Flutter, flutter.dev

[4] Soyons acteurs du développement (mobile) durable, Gabriel Adgeg, Android Makers, 04/2020

[5] swift-evolution, Github

[6] Flutter Architecture Samples, fluttersamples

[7] Apps take flight with Flutter, flutter.dev

[8] Why Airbnb is Moving Off Of React Native, Adam Conrad, Software Engineering Daily, 09/2018

[9] Flutter, Github

[10] React Native, Github

[11] Questions tagged Flutter, Stack Overflow

[12] Questions tagged React Native, Stack Overflow

[13] Questions tagged Xamarin, Stack Overflow

[14] Stack Overflow Trends, Stack Overflow

[15] Flutter for Android developers, flutter.dev

[16] Flutter for iOS developers, flutter.dev

[17] Flutter for web developers, flutter.dev

[18] Flutter for React Native developers, flutter.dev

[19] Flutter Widget of the Week, Youtube

[20] Flutter Google IO, Youtube

[21] From mobile app to web app, Flutter Engage, Youtube, 03/2021