All U Need Is Pizza 🍕

Damien Chazoule
13 min readNov 12, 2019

Il y a quelque temps de cela (mi-Septembre), je me suis mis au défi de coder pendant 100 jours consécutifs. À la différence du challenge #100DaysOfCode, je n’ai pas publié mon avancement sur Twitter. Pendant cette durée, j’ai expérimenté plusieurs frameworks (frontend / backend) sous un thème commun : la création, la lecture, la mise à jour et la suppression de… pizzas !

NB : Mon amour pour la gastronomie Italienne à eu raison de moi sur ce coup-là…

Arrivé à mi-chemin de mon objectif, je vous explique dans cet article ma démarche, ainsi que les choses que j’ai découvertes en éprouvant les frameworks (et librairies) frontend suivants : Angular, React, Svelte et Vue. Mon point de vue sera orienté composant du fait des technologies utilisées.

Le résultat final est disponible ici. Voyez cet article comme un retour d’expérience.

Introduction

Avant d’aller plus loin, et surtout avant d’ouvrir mon IDE favori (VSCode), il m’a fallu trouver une idée. J’avais déjà pour objectif de tester plusieurs frameworks et / ou langages (après tout, je suis un passionné, je mange du code matin, midi et soir), il ne me manquait donc plus que le thème…

Au début, je pensais réaliser une série de compteurs, mais l’idée étant trop classique, j’ai choisi de l’abandonner. Quelques jours plus tard, lors d’un passage dans une pizzeria, au moment de faire mon choix, je me dis : “Tiens ! Cela serait génial de pouvoir créer ses propres pizzas !”

La voilà mon idée : un CRUD ayant pour sujet principal la pizza. L’idée du CRUD n’est pas très originale… Cependant, il m’a permis de mettre au point plusieurs boilerplates (certains constitués de routes, d’autres implémentant un paradigme de programmation réactive) pour mes développements futurs. Autre point important, j’ai décidé de coder une série d’applications isomorphes en termes de rendu graphique, c’est-à-dire que le visuel devra être le même, peu importe le framework (ou la librairie) utilisé.

Design

Première étape : le design ! Le style est un élément capital lors de la création d’une application web. N’étant pas UI/UX, j’ai opté pour un design simple avec un soupçon de Material Design (pour les couleurs). J’ai modélisé les différents écrans grâce au super outil qu’est Figma. Je n’utilise pas pleinement les fonctionnalités de l’application, néanmoins, l’outil n’a rien à envier à Sketch. Petite parenthèse : Figma peut être agrémenté de fonctionnalités (sous forme de plugins) dont une indispensable : SVG To JSX ; extrêmement pratique pour un développeur React !

Maquettes réalisées avec Figma

Bref, une fois les maquettes réalisées, je me suis offert une piqûre de rappel sur le CSS. Particulièrement sur les notions de flexbox et de grid layout que je ne maîtrisais pas pleinement (CSS3 étant modulaire, on en apprend quasiment tous les jours). J’ai réellement commencé à coder à partir de ce moment-là : ouverture de VSCode, création d’un fichier .scss, mains sur le clavier et go !

Séduit par le modèle atomique de Brad Frost, j’ai écrit les différentes parties de mon application en suivant ce principe de décomposition : atomes, molécules, organismes, etc… Ainsi, vous trouverez facilement les couleurs en tant qu’atomes, ou encore les “briques” qui vont composer mon application (telle que l’élément de liste) en tant qu’organismes. Le modèle atomique est un concept vraiment intéressant, et idéal pour organiser son code lorsqu’on réalise un projet de Design System. Encore une fois, je ne suis pas UI/UX, mon organisation n’est donc pas parfait, mais suivre ce modèle m’a permis d’optimiser le découpage de mes fichiers SASS.

Et voilà, quelques lignes de code plus tard (et quelques modifications de maquettes aussi), j’ai enfin une application statique complète prête à être “dynamisée”.

Architecture

Deuxième étape : l’architecture du code ! Comme expliqué précédemment, je souhaite créer des applications isomorphes les unes des autres. J’ai poussé le concept un peu plus loin en essayant d’avoir une organisation commune. Mis à part pour le framework Angular où l’organisation du code est déjà profondément définie à l’initialisation, j’ai réussi à obtenir l’architecture applicative suivante :

+-- public             # 'index.html' Is Here
+-- src
+-- assets # Resources Like Fonts
+-- components
+-- layers # Dumb Components
+-- containers / views # Smart Components
+-- services
+-- utils # Utility Methods
+-- index.(s)css # Global Styles
+-- index.js / main.js # App Entry Point
+-- pizzas.json # Data
+-- .prettierrc # Formatter Config
+-- package.json

Les habitués de React et de Vue reconnaîtront ce mode de fonctionnement. Pour les autres, voici un bref récapitulatif du contenu des différents dossiers :

  • public : Fichiers statiques dont l’index.html et le favicon.png ;
  • assets : Ressources appelĂ©es par le code, telles que les polices de caractères ;
  • components : Composants du projet dĂ©coupĂ©s selon le modèle Smart Vs. Dumb (voir plus bas) ;
  • services : MĂ©thodes faisant les appels asynchrones permettant notamment de rĂ©cupĂ©rer des donnĂ©es ;
  • utils : Autres mĂ©thodes utilitaires.

NB : En Angular, le dossier services est propice à accueillir de “vrais” services qui seront ensuite injectés dans l’application.

DĂ©veloppement

Maintenant que nous avons la structure à l’esprit, lançons-nous dans le développement de composants. Pour ce faire, et afin d’éviter la redondance de code, j’ai opté pour un découpage en deux parties : Smart Vs. Dumb. Les Dumb Components (ou composants de présentation) sont dépourvus de logique métier, et sont souvent associés à une portion de style pour pouvoir mieux maîtriser le rendu graphique. Au contraire, les Smart Components (parfois appelés “conteneurs”) consomment les composants de présentation tout en y injectant des données. Pour ce projet de CRUD, j’ai choisi de créer 3 vues qui réfèrent directement à 3 composants de type “conteneurs”. Le reste de mes composants seront dédiés au visuel.

NB : Dan Abramov explique plus en détail ce mode de fonctionnement dans son article. Bien qu’il ait changé de point de vue récemment, je persiste à utiliser ce modèle (notamment avec d’autres frameworks orientés composants) afin de conserver des composants de taille acceptable.

React

Très vite, je me suis orienté vers React pour la réalisation de ma première application web. J’ai l’habitude de travailler avec la librairie de Facebook depuis plusieurs années. La difficulté de la syntaxe .jsx disparaît rapidement, offrant à son développeur plus de lisibilité dans les composants qu’il construit.

Pour créer un projet React, rien de mieux que de faire appel à l’utilitaire CLI create-react-app. Cette dépendance permet de générer une structure de code stable et flexible (embarquant l’indispensable bundler Webpack) de manière très simple.

Block.jsx

On peut lire ce premier composant React, de la manière suivante : c’est un composant stateless qui prend 3 propriétés, dont une (children) qui permet de déléguer du contenu dans ce même composant. Ici Block.jsx est un composant de présentation, et n’a donc pour vocation que de mettre en forme les données qui lui sont passées. La notion stateless fait référence au fait que le composant n’est pas écrit de manière explicite en étant étendu d’une instance de composant de React (sinon cela aurait été un composant dit stateful).

List.jsx

Dans ce second composant (toujours écrit de manière stateless), on remarque deux choses : l’usage de plusieurs composants de présentation (dont notre Block.jsx) et l’omniprésence des hooks. Le “conteneur” List.jsx ci-dessus, va se charger de faire appel aux Dumb Components, et de les enrichir d’un ensemble de données.

Apparaissant avec la version 16.8.0, les hooks permettent de rajouter de la logique aux composants qui en sont dépourvus (c’est-à-dire les composants stateless). En optant pour ce principe, React a clairement définit son appartenance au paradigme de programmation fonctionnelle, se détachant ainsi des autres frameworks orientés composants.

NB : Dans la suite de cette article, on s’amusera à comparer les composants Block et List (notamment en termes de syntaxe) avec les autres librairies présentées ci-dessous.

Vue

En parallèle de React, j’ai rapidement (re)développé cette même application de CRUD avec le framework Vue. Le framework communautaire n’a rien à envier de ses principaux concurrents : Angular et React. Fonctionnellement, il est à mi-chemin entre ces deux derniers, avec notamment les notions de directives ou encore de DOM virtuel.

Tout comme React, pour créer mon projet, j’ai utilisé l’outil CLI de Vue. À la différence de son homologue de chez Facebook, il permet d’agrémenter la structure du projet de dépendances optionnelles (telles que SASS, TypeScript on encore Prettier). Cerise sur le gâteau, tous ces choix peuvent s’effectuer graphique ! En effet, dans les dernières versions, @vue/cli est capable d’”émuler” le package.json.

Block.vue

Contrairement au framework à la librairie précédente, on retrouve explicitement du HTML et du JavaScript. La force de Vue réside dans l’écriture de SPCs (Single Page Components). La syntaxe des fichiers .vue permet au développeur d’avoir accès au HTML, au JavaScript (et même au CSS) dans un seul et même fichier (par composant bien sûr).

En mettant de côté la syntaxe, on s’aperçoit que Block.vue possède maintenant 2 propriétés (un numérique et une chaîne de caractères comme précédemment). Cette fois-ci, le passage de contenu s’effectue grâce à l’élément <slot />. Il est d’ailleurs possible de nommer ces éléments afin de dynamiser plusieurs portées du composant de présentation.

List.vue

Toujours en faisant abstraction de la syntaxe. On remarque à nouveau l’usage “massive” de composants de présentation dans la partie dédiée au template HTML. Vue hérite du fonctionnement par directives d’AngularJS. Ainsi on retrouve les notions v-bind et v-on qui permettent respectivement d’évaluer du code, et de jouer un événement du DOM. Dans l’exemple ci-dessus, j’utilise des raccourcis :

  • : Ă©quivaut Ă  la directive v-bind
  • @ Ă©quivaut Ă  la direction v-on

Pour les adeptes d’Angular, Vue conserve le principe de binding bidirectionnel grâce à la directive v-model. Monter en compétence sur cette technologie est plus facile qu’il n’y parait. La difficulté de Vue réside (peut-être) dans l’utilisation du this pour la partie JavaScript.

Le framework créé par Evan You a encore de beaux jours devant lui puisqu’il représente une véritable alternative à la librairie de Facebook. De plus, sa communauté attend de belles choses d’ici 2020, avec notamment la prochaine version majeur de Vue.

NB : Bien que la popularité de ce framework soit faible face à React, il représente toutefois une belle réussite de projet open-source. En effet, depuis le 3 Novembre 2019, Vue est (enfin) passé devant Angular en termes de téléchargements sur NPM.

Svelte

Après React et Vue, j’ai décidé de me confronter à un challenger : Svelte ! D’après Rich Harris (son créateur), Svelte se définit non pas comme un framework, mais plutôt comme un compilateur. Il est aussi radicalement plus léger que ses prédécesseurs, et se prône même comme étant plus performant. À l’inverse de React et Vue, qui utilisent un DOM virtuel pour calculer les changements et (re)rendre seulement la partie du DOM impacté, Svelte agit directement sur le DOM tout en restant réactif en cas de mutations de données.

Pour débuter un projet avec Svelte, il suffit de cloner un template disponible sur le dépôt dédié et de rapatrier les dépendances via le gestionnaire de paquets (la librairie degit peut faire ce travail pour vous). En général, les templates sont configurés pour fonctionner avec le bundler RollupJS à l’instar des autres CLI qui initialisent leurs projets respectifs en embarquant Webpack.

Block.svelte

La syntaxe du composant Block.svelte ci-dessus n’est pas si différente de Vue. En effet, on s’aperçoit très vite des similitudes avec les SPCs de Vue. À la différence que Svelte arrive à s’absoudre de l’usage du this. Depuis l’arrivée de la troisième version du compilateur, plus besoin de se soucier du this.

Tout comme Vue, le composant de présentation Block.svelte, contient 2 propriétés exposées au composant parent via le mot-clé export, ainsi que l’élément <slot /> qui fonctionne de la même manière que le framework communautaire (il est donc possible de nommer les différentes portées).

NB : Je ne sais pas si Svelte est suffisamment mature pour lui imposer le découpage de composants Dumb Vs. Smart, mais je persiste à utiliser ce modèle ici.

List.svelte

Dans ce second composant Svelte, je charge le jeu de données relatif aux pizzas grâce à la fonction onMount de la librairie. Les données sont ensuite injectées à mes composants de présentation. La réactivité de Svelte, réside dans son langage. Le compilateur choisit d’utiliser le symbole $: pour rendre une variable réactive. En effet, en JavaScript cet usage va lier une variable à une autre. Ainsi, lorsque la variable liée sera modifiée, le compilateur recalculera le changement et répercutera son impact sur le DOM.

Le compilateur possède une syntaxe vraiment intéressante avec notamment beaucoup de raccourcis. Je vous conseille d’aller faire un tour sur le site de Svelte, la documentation est relativement bien faite, et l’apprentissage se fait grâce à un playground. Le compilateur de Rich Harris a toutes ses chances d’arriver sur le podium des frameworks orientés composants dans les années à venir (bien qu’il ne s’agisse pas vraiment d’un framework, comme React après tout). La dernière version de Svelte embarque deux superbes implémentations :

  • Sapper : ImplĂ©mentation dĂ©diĂ©e au fonctionnement SSR (Server-Side Rendering) ;
  • Svelte Native : ImplĂ©mentation dĂ©diĂ©e au dĂ©veloppement mobile, via NativeScript.

Angular

J’ai mis beaucoup de temps avant de me (re)mettre au framework de Google. Je suis même passé par une phase de programmation orientée objet avant de l’éprouver à nouveau. La raison : l’outil CLI d’Angular (@angular/cli) génère une structure de projet trop complète. C’est-à-dire qu’avant même d’avoir commencé à développer des composants, on dispose déjà de tous les outils (et surtout d’une panoplie de fichiers de configuration). Personnellement, je préfère greffer mes dépendances au fur et à mesure de l’avancement de mon projet.

Vous l’aurez compris, pour créer un projet rapidement et simplement avec Angular, utiliser @angular/cli. Dans l’ensemble, la CLI d’Angular est vraiment très puissante, elle permet notamment de générer les éléments nécessaires au projet : composants, services, directives, etc… Les fichiers ainsi générés seront directement instanciés dans le module principal d’Angular : app.module.ts. Les dernières versions d’@angular/cli permettent même le déploiement de votre code sur des plateformes dédiées telles que Now (by Zeit).

block.component.ts

Par rapport aux frameworks (et librairie) présenté(e)s ci-dessus, on voit tout de suite la différence dans l’écriture des composants. Angular supporte officiellement (et nativement) le sur-ensemble typé de JavaScript qu’est TypeScript. Développé par Microsoft depuis 2012, TypeScript apporte de la rigueur dans les structures de données JavaScript. Idéal pour les développeurs qui viennent de la programmation orientée objet / Parfois trop lourd pour les développeurs qui préfèrent la programmation fonctionnelle.

NB : À noter que React et Vue peuvent eux aussi être surchargés par TypeScript (d’ailleurs @vue/cli propose ce choix à l’initialisation de votre projet).

À nouveau, le composant de présentation block.component.ts expose 2 propriétés (respectivement height et color) grâce à un procédé appelé décorateur (@Input). Les décorateurs font partie intégrante du framework de Google, et permettent de rajouter du comportement à la fonction ou la variable qu’il préfixe. Enfin, la délégation de contenu s’effectue avec l’élément <ng-content /> en Angular.

list.component.ts

Le second composant TypeScript ci-dessus, contient plus de code que le précédent. On remarque ici encore l’omniprésence des composants de présentation (dont block.component.ts), l’usage d’un décorateur (@Component) et surtout le typage de variable ! La notion d’interface permet de déclarer une structure de données pour ensuite typer les objets du code JavaScript TypeScript. Le décorateur ici présent sert à transformer la classe qui suit en composant Angular, et lui associer des propriétés telles qu’une portion de template HTML (d’ailleurs le HTML peut être dissocié du code TypeScript, et affilié au composant par son chemin via templateUrl).

J’ai un avis assez tranché sur Angular. Le framework de Google est complet, peut-être trop. Par exemple, il fournit nativement des modules pour la gestion des routes, ou encore pour la gestion des formulaires (ce que d’autres frameworks n’implémentent pas pour laisser cela à des dépendances externes spécifiques). La notion qui m’intéresse le plus est le paradigme de programmation réactive par flux : RxJS (donc pas vraiment propre à la librairie). Angular a le mérite d’exister pour le plus grand bonheur des développeurs Java.

The End

J’ai pris beaucoup de plaisir à expérimenter ces différentes technologies. Je m’aperçois que finalement ces frameworks (et librairies) ont beaucoup de points communs, notamment dans l’écriture de composants. La différence des uns et des autres s’effectue à la fois sur la syntaxe (.jsx, .vue, .svelte, .ts) et sur le mode de fonctionnement. En effet, certains préconisent l’usage d’un DOM virtuel pour calculer le changement et l’opérer rapidement, alors que d’autres préfèrent agir directement sur le DOM, tout en étant réactif.

Comme beaucoup de projets, le choix des technologies dépend majoritairement des compétences des développeurs, et de la finalité du projet. Typiquement, les projets possédant beaucoup de ressources backend (Java) s’orienteront plus facilement vers un développement web basé sur Angular. A contrario, d’autres se méfient du framework de Google à cause de la rupture qu’il y a eu entre AngularJS et Angular 2+. Ils préfèrent prendre parti pour la librairie de Facebook (ou encore pour le framework communautaire Vue qui a le vent en poupe en ce moment).

Je pense qu’au vu des enjeux qui se dessinent pour les années à venir, à savoir l’accessibilité et les technologies embarquées (wearables, Smart TV, etc…), les compilateurs tels que Svelte ont une carte à jouer du côté des performances. Ces librairies sont à prendre en considération dès aujourd’hui, peut-être même qu’on assistera à la démocratisation des frameworks agnostiques de composants (Polymer, Stencil) d’ici un ou deux ans… Affaire à suivre !

J’espère que cet article vous aura donné envie d’en savoir plus sur ces technologies. Encore une fois, je vous présente ici une ébauche de ce qu’il est possible de faire avec des frameworks (et librairies) frontend orientés composants. Les fonctionnalités ne vont pas très loin (pas de state management ou encore de routing), mais le concept principal de CRUD permet d’initialiser plusieurs boilerplates bien utiles ! Pour ma part, je retourne à mon challenge de code, avec pour objectif (dans cette deuxième partie) de développer des APIs RESTful qui exposeront… des pizzas bien sûr !

Sources

--

--

Damien Chazoule

Développeur FullStack passionné d'informatique depuis plus d'une décennie