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.

Flutter for web architecture

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)
Flutter for web - Premier écran
http://localhost:8080

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  :

A très bientôt pour d’autres annonces autour de Flutter.