Comment Angular 2 a réinventé GWT

Je me rappellerai toujours de ma première confrontation avec Angular en 2012. Invité au DevFest de Nantes, j’étais chargé d’animer une présentation sur GWT et l’Offline qui se déroulait en même temps qu’une session sur ce Framework encore balbutiant. Le speaker n’était autre qu’un jeune membre de l’équipe de développement Angular tout droit venu du siège de Google aux Etats-Unis. Ce jour-là, aux dires de tous les participants, sa présentation et son sujet avait littéralement envouté le public. Il se trouve que ce jour-là, par un heureux hasard, nous nous sommes retrouvés Votja et moi dans la même salle d’embarquement et nous avons échangé de longues minutes sur le sujet « Angular vs GWT ». Deux Framework Web créés par Google et mis en concurrence. En 2012, la pérennité de GWT commençait déjà à faire débat suite au départ de plusieurs cadres du projet.

Je me rappelle encore aujourd’hui de cette discussion acharnée en salle d’embarquement de l’aéroport de Nantes. En 2012, JavaScript n’est pas le JavaScript de 2017, ce langage est encore un langage de script faiblement typé, horriblement lent lorsqu’il n'est pas optimisé et surtout non outillé. Pendant cet échange, je rétorquais à mon homologue qu’il ne m’était pas concevable de construire une application complexe en JS car il manquait tout ce que Java possédait, les classes, les interfaces, le typage fort, la complétion automatique, les packages et le refactoring, sa réponse était cinglante : « Tu appartiens à une génération d’architectes Java qui construisent des usines à gaz avec un langage verbeux en accumulant des couches sans réel intérêt » (sic !). Son argumentation était basée sur le fait qu’Angular était un Framework d'une simplicité extrème bâti sur un langage peu verbeux. Pour lui, le typage faible apporté par JS était une force car il permettait de réaliser un databinding dynamique simplement en modifiant le code HTML avec un balisage spécifique. D’ailleurs, les présentations Angular avait un succès fou à cette époque car elles déroulaient toutes la fameuse application de Todo list dont l’environnement de développement se résumait à changer du code JS dans un éditeur texte pour le lancer avec un simple F5 dans le navigateur. Votja Jina, qui avait aussi été un ancien développeur GWT, me soutenait qu’il était ridicule de compiler du Java pour en faire du JS car pour lui GWT était une sorte de boite noire trop complexe.   

Pendant ces 5 ans qui ont vu l’avènement et la généralisation d’Angular 1 sur le marché du Web, nous nous sommes toujours refusés chez DNG à adhérer à ce framework. Non seulement pour les raisons liées à JavaScript et son outillage mais aussi et surtout du fait de son architecture. Pour résumer très brièvement le fonctionnement d’Angular 1, imaginez qu’à chaque fois que vous lanciez Word ou Excel celui-ci se mette à s’auto-compiler. Pour mettre en œuvre le databinding, Angular utilise un analyseur syntaxique qui parcourt récursivement la structure des templates HTML pour créer des arbres DOM complets sur lequel sont lancés des traitements (expressions, interpolation, pipes, …). Or, lorsque vous mettez en production une application, la structure des pages ne changent pas et pourtant la même analyse syntaxique est réalisée. Ce qui fait l’essence de l’architecture Angular 1 n’a pas de sens surtout lorsqu’on y rajoute les CSS, les innombrables artéfacts que constituent une application JS. C’est un amoncellement de centaines de scripts JS inter-dépendants sans chercher à dissocier le code utile du code inutile. Des choix d’autant plus étonnants quand on connait le fonctionnement de GWT. GWT et Coffescript dans une moindre mesure avaient déjà compris qu’il était indispensable de créer un compilateur « intelligent » capable de packager des assets ou artéfacts dans des sortes de bundle minifié ultra-optimisé basé sur un langage fortement typé et structuré. Angular 1 embarque l’essentiel de son runtime à l’exécution (ils appellent cela un JIT), c’est un non-sens notamment dans un contexte embarqué sur des smartphones (utilisation déraisonnable des batteries et surtout du CPU).

Il aura fallu attendre l’arrivée de TypeScript associé à des outils de packaging tels que Webpack ou Browserify pour que Angular commence enfin à comprendre qu’un runtime doit être allégé par des opérations de compilation et d’optimisation. La compilation AOT (Ahead Of Time) n’est ni plus ni moins que ce que GWT fait avec son compilateur, les linkers et les générateurs de code, sans compter l’optimisation du JS avec Closure (le Tree Shaking). 

TypeScript est un excellent compromis entre Java et C#. Il réussit à réunir communauté JS, communauté Java et .NET. TypeScript s’intègre facilement aux bibliothèques JS existantes, il est conçu par Anders Heljerg, inventeur de C# chez Microsoft et trouve un écho auprès des développeurs Java grâce à ses éléments de syntaxe. Avec le concept AOT, un simple « ngc »  permet de générer une permutation, pardon un bundle JS, dont les artéfacts inutiles ont été épurés. Grâce à Typescript, JavaScript a enfin embrassé les concepts des langages objets et de la compilation JavaScript.  

Angular 2 prend également le partie de générer du TypeScript en mode Ahead Of Time (là où GWT génère du Java avec UiBinder) avec la création d’un AST (Arbre syntaxique créé après le parsing des templates). En fin de compte, en 5 ans Angular s’est rapproché de GWT comme jamais. Angular 2 a adopté la compilation et la génération de code fortement typé, l’utilisation de JS comme simple assembleur du Web. Compte tenu de cette architecture, on arrive d’ailleurs à une situation assez rocambolesque, les third-party librairies (librairies tierces) écrites en JS constituent désormais le principal fardeau pour Angular. En effet, comment intégrer du code JS classique dans toute cette chaîne sachant qu’il y a une structuration particulière des modules, que les artéfacts (images, CSS, JS,…) doivent être déclarés d’une certaine manière pour être optimisés. En résumé, tous les problèmes posés par l’intégration JavaScript dans une application Java/GWT. En réinventant un par un tous les concepts de GWT, Angular 2 doit faire face aux même problèmes ; Difficulté d’avoir des messages d’erreurs clairs lorsqu’on passe par des générateurs de code intermédiaires, difficulté de debuguer facilement des bibliothèques JS externes, accroissement du fichier bundle.js généré, nécessité de créer un mode Dev et un mode Prod (comme GWT !). Même le code splitting, la faculté de diviser du code JS en plusieurs parties pour les charger de manière asynchrone est une des fonctionnalités phares de Webpack.

Ceci étant, Angular 2 va dans le bon sens et réussira probablement à corriger tous ces points qui pénalisent encore aujourd’hui parfois GWT. La principale différence avec GWT est l’intégration d’une bibliothèque. Là où GWT émule les classes du JDK et du Framework Java, Angular laisse la liberté du choix des composants et du modèle RPC. En ce sens, il se rapproche plus de la prochaine version de GWT qui souhaite se séparer des Widgets et créer un transpileur.

L’histoire du développement logiciel est parfois un chemin sinueux, souvent cyclique où l’amnésie de certains pousse à créer différemment et réinventer des choses plutôt que chercher à les améliorer. Angular 2 est devenu inévitablement une boite noire tout comme GWT en son temps. Et il n'a pas d'autres choix car le Web est par essence complexe. Et ceux qui, depuis 5 ans, ont choisi d’attendre ou de ne pas décider auront eu raison. En attendant, je retiens la remarque d’un de mes camarades lorsqu’il développe avec Angular 2 associé à un backend Java : « La syntaxe TypeScript et Java sont tellement proches qu’on se met souvent à écrire du Java dans du code TypeScript et inversement, c’est pénible ».

On l’oubliait mais l’idée de GWT était aussi d’unifier le langage entre client et serveur…

Sami JABER
DNG Consulting