Il y a quelques mois nous avions rédigé un article centralisant les grandes annonces du Flutter Live London 2018 : https://blog.ineat-group.com/2018/12/flutter-live-london-2018/.
Vous ne connaissez pas Flutter ?
Flutter est une solution développée par Google permettant de créer des applications Android et iOS avec un unique code source. De par son architecture, Flutter a démontré sa flexibilité en générant des applications mobiles et Desktop (macOS, windows, linux). Les applications sont développées avec le langage Dart en compilation anticipée nommée : AOT.
AOT, signifiant “ahead of time”, est utilisé dans certains langages compilés tels que le C et le C++. Ces langages sont compilés en binaire, ce qui fait de Flutter un framework permettant de générer des applications natives.
Mais pourquoi évoquer la conférence Flutter Live London 2018 au début de l’article ?
Parmi les grandes annonces le projet Hummingbird : une solution permettant de générer un site web à partir de Flutter.
Imaginez développer une application Android, iOS, Desktop et web à partir d’un seul code source. Cela semble trop beau pour être vrai !
Jusqu’à présent rien n’était disponible et nous attendions avec impatience une éventuelle annonce officielle à la Google IO 2019.
Et c’est chose faite ! Google a officialisé Flutter for web. Bien que celui-ci soit en version preview, cela suffit pour satisfaire les amoureux de Flutter.
Architecture
Flutter for web est une implémentation permettant de rendre compatible le rendu pour les navigateurs. Il combine le DOM, canvas, et CSS afin de pouvoir dessiner les widgets qui composent l’application.
Le compilateur dart2js permet de transformer les fichiers dart en Javascript pour être interprétés par le navigateur.
Malheureusement à ce stade Flutter for web est décoléré du SDK Flutter. L’ensemble des widgets sont des “forks” du SDK ayant des noms de package légèrement différents. Mais pas d’inquiétude Google travaille déjà sur l’unification des deux noyaux.
Maintenant voyons ensemble comment construire un projet Flutter pour le web en 3 étapes
Etape 0 : vous découvrez Flutter
Vous venez de découvrir Flutter, pas de problème ! Je vous invite à consulter le lien suivant : https://flutter.dev/docs/get-started
Etape 1 : installer l’environnement
Commencer par vérifier les versions de Flutter et Dart installés sur votre poste.
Lancer la ligne de commande suivante :
> flutter --version
Vous obtiendrez un résultat similaire à ceci :
Flutter 1.5.4 • channel unknown • unknown source Framework • revision b593f5167b (3 weeks ago) • 2019-04-22 07:51:33 -0700 Engine • revision ca31a7c57b Tools • Dart 2.3.0 (build 2.3.0-dev.0.1 cf4444b803)
Dans le cas où Flutter & Dart ont respectivement une version inférieure à 1.5.4 et 2.3 alors effectué une montée de version :
> flutter upgrade --force
Afin de construire un projet Flutter pour le web, il est indispensable d’installer le package webdev :
> flutter packages pub global activate webdev
Ce package permet de développer et déployer des applications web avec Dart. C’est ce qui est utilisé par exemple sur AngularDart : https://angulardart.dev/guide/setup.
Assurez-vous que votre $PATH est correctement configuré avec le chemin de votre SDK Flutter :
export PATH="$PATH":"$HOME/Library/Flutter/sdk/.pub-cache/bin" export PATH="$PATH":"$HOME/Library/Flutter/sdk/bin/cache/dart-sdk/bin"
Suite à cela la commande webdev devrait être disponible :
> webdev A tool to develop Dart web projects. Usage: webdev <command> [arguments]
Etape 2 : configurer son projet
Configurer le fichier pubspec.yaml
Pour construire un projet Flutter pour le web il faut ajouter les dépendances suivantes :
- flutter_web
- flutter_web_ui
Note : Ici nous n’importons pas le SDK Flutter mais deux librairies tierces.
Les dépendances se situent directement sur le repository github : https://github.com/flutter/flutter_web.
Ensuite le code Dart doit être compilé en JavaScript, pour cela ajouter les dépendances de build suivantes :
- build_runner
- build_web_compilers
Vous obtiendrez alors le fichier pubspec.yaml suivant :
name: ineat_flutter_web description: An app built using Flutter for web environment: sdk: '>=2.3.0-dev.0.1 <3.0.0' dependencies: flutter_web: any flutter_web_ui: any dev_dependencies: build_runner: ^1.4.0 build_web_compilers: ^2.0.0 dependency_overrides: flutter_web: git: url: https://github.com/flutter/flutter_web path: packages/flutter_web flutter_web_ui: git: url: https://github.com/flutter/flutter_web path: packages/flutter_web_ui
Maintenant il vous suffit de récupérer les dépendances :
> flutter packages upgrade
Le code dart
Le code d’une application Flutter se situe dans le répertoire /lib. Par défaut vous devriez avoir un fichier main.dart correspondant au point d’entrée de votre application. Voici le contenu du fichier :
// lib/main.dart import 'package:flutter_web/material.dart'; // Fonction de démarrage de l'application void main() => runApp(MyApp()); // Ecran de démarrage class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home: Scaffold( appBar: AppBar( title: Text("Mon premier site en flutter"), ), body: Center( child: Text("Hello world"), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.edit), onPressed: () {}, ), ), debugShowCheckedModeBanner: false, ); } }
Habituellement la création d’un projet entraîne la création de deux répertoires : android et ios. Ces répertoires sont des projets vides ayant le rôle de charger le code dart compilé.
Puisque nous faisons un projet web, nous ajoutons un répertoire /web qui contiendra le code HTML permettant de charger le code dart compilé en Javascript.
Ajouter le fichier web/index.html :
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link href="https://fonts.gstatic.com" rel="preconnect" crossorigin> <link href="https://fonts.gstatic.com/s/materialicons/v42/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2" rel="preload" as="font" crossorigin> <script defer src="main.dart.js" type="application/javascript"></script> </head> <body> </body> </html>
Ce fichier HTML est la page qui sera affichée à l’écran. Notez que celle-ci charge un fichier Javascript main.dart.js. Ce dernier sera généré par le compilateur dart2js à partir du fichier main.dart que vous allez créer dans le répertoire /web.
Ajouter le fichier web/main.dart :
import 'package:flutter_web_ui/ui.dart' as ui; import 'package:ineat_flutter_web/main.dart' as app; main() async { await ui.webOnlyInitializePlatform(); app.main(); }
Ce fichier initialise votre application Flutter for web. Par défaut la méthode webOnlyInitializePlatform() charge l’ensemble de vos médias dans le répertoire /web/assets ; mais il est possible de modifier le chemin :
import 'package:flutter_web_ui/ui.dart' as ui; import 'package:ineat_flutter_web/main.dart' as app; import 'package:flutter_web_ui/src/engine.dart' as engine; main() async { await ui.webOnlyInitializePlatform( assetManager: engine.AssetManager( assetsDir: "mon_nouveau_repertoire_assets" ) ); app.main(); }
Félicitation ! Vous venez de créer votre première application Flutter for web. Il ne reste plus qu’à la tester.
Lancer l’application
Lorsque vous souhaitez lancer votre application, vous avez la possibilité d’utilisé le Hot Reload. Cette fonctionnalité permet de recharger à chaud le code de l’application en injectant ce qui a été modifié.
Lorsque vous lancez l’application, vous avez la possibilité de l’activer ou non.
Démarrer sans Hot Reload :
> flutter packages pub global run webdev serve
Démarrer avec Hot Reload :
> flutter packages pub global run webdev serve --auto restart
Votre site web sera accessible via l’url http://localhost:8080 :
[INFO] Serving `web` on http://localhost:8080 [INFO] Running build completed, took 2.3s [INFO] Caching finalized dependency graph completed, took 153ms [INFO] Succeeded after 2.5s with 12 outputs (2067 actions)
Build & release l’application
La construction de l’application va générer un répertoire build à la racine du projet. Pour construire votre projet il faut lancer la commande :
> flutter packages pub global run webdev build
Une release permet de compacter le code Javascript afin d’optimiser le chargement de la page :
> flutter packages pub global run webdev build --release
Conclusion
Après quelques jours d’expérimentation, nous avons été convaincus par Flutter for web. La version disponible n’est qu’une preview mais permet déjà de voir les différentes possibilités de la solution.
Pour l’instant la promesse initiale de Flutter qui est de coder une application avec un unique code source n’est pas encore respectée. Les widgets importés dans l’application n’ont pas le même package que celui du SDK :
- package:flutter pour le SDK classique
- package:flutter_web pour la version web
Mais ceci n’est que provisoire, sur son projet github Google annonce ceci : “Our goal is to add web support as a first-tier platform in the Flutter SDK alongside iOS and Android”.
Je vous invite également à consulter une démonstration que nous avons confectionné pour cet article :
- Site web : https://ineat.github.io/hummingbird/
- Code source : https://github.com/ineat/hummingbird
A très bientôt pour d’autres annonces autour de Flutter.