Éléments de la Stack JavaScript
À quoi servent NPM / Yarn / Gulp / Grunt / Bower / Browserify / Webpack...?
Pourquoi cet article ?
La stack JS contient un gloubi-boulga d'outils qui permettent de tout faire et ce de toutes les manières possibles. Le gros problème est que le périmètre de la plupart de ces outils s'intersectionne avec le périmètre d'un ou plusieurs autres outils, ce qui ajoute autant de confusion pour comprendre quoi utiliser et dans quelles circonstances. L'idée est ici d'expliquer l'intention se cachant derrière chaque outil pour s'en servir au mieux dans la fabrication d'une application JS.
Définitions :
Babel : Babel est l'équivalent de TypeScript mais porté par la communauté. Son rôle consiste à transpiler de l'EcmaScript 6 / 7, c'est-à-dire du JavaScript futur et pas encore implémenté, vers du JavaScript 5 interprété et compatible avec les navigateurs actuels.
Bower : Bower est un utilitaire permettant de gérer les dépendances de votre projet. Là où Bower s’essouffle par rapport à Yarn et NPM c'est qu'il ne gère pas les dépendances transitives mais a contrario en il les gère en "flat". Autrement dit, si une lib dépend d'une autre lib qui dépend elle-même d'une autre lib et ainsi de suite, ce sera à vous de parcourir le graphe des dépendances à la main et de les ajouter dans votre conf Bower ; là où Yarn et NPM vous demandent de ne déclarer que la lib d'origine.
Browserify : Browserify est un outil de packaging, en conséquence il vous permet de fabriquer le ou les bundles de vos applications web en les minifiant. A l'instar de Bower qui peine face à Yarn et NPM, Browserify s'essoufle vis-à-vis de Webpack qui fournit des fonctionnalités d'optimisation du code et de suppression du code mort particulièrement performantes.
Grunt : C'est un "tasks runner", c'est-à-dire que vous allez coder ou déclarer à Grunt une tâche à faire et Grunt saura la répéter autant de fois que vous le lui aurez demander. Grunt va même au-delà puisqu'il vous permet de définir un ordre d'exécution et de définir des dépendances entre vos tâches.
Gulp : Gulp fait partie de la famille des "tasks runner", c'est-à-dire qu'à l'image de Grunt vous aller lui déclarer les tâches à exécuter ainsi que leurs dépendances. Gulp les rejouera correctement sans tressaillir. Là où Gulp tire son épingle du jeu, c'est qu'il dispose d'un panel dépassant à cette heure la dizaine de millier de plugins qui fournissent des actions préétablies tout comme ANT le propose en Java. En ce sens, Gulp vous permet d'allier sans contrainte l'exécution de plugin avec une conf écrite sous la forme d'un code réactif en JS.
Jasmine : C'est un framework permettant d'écrire des tests en JavaScript. Ces derniers peuvent être au niveau unitaire (façon JUnit) ou fonctionnel / intégration (façon Cucumber). En général Jasmine est considéré comme faisant partie des frameworks orientés BDD mais il est suffisamment souple pour le TDD.
Karma : C'est un outil permettant de charger une suite de tests écrits en Jasmine ou en tout autre chose. Le concurrent le plus sérieux est MochaJS qui est une sorte de medley entre Karma et Jasmine.
NodeJS : C'est une machine virtuelle qui permet de faire tourner du JavaScript côté serveur.
NPM : C'est le gestionnaire de paquets fournit avec NodeJS et qui permet de récupérer les dépendances transitives de vos projets (façon Maven). Aparté : certains disent que NPM signifie Node Package Manager mais l'auteur atteste que non.
PhantomJS : C'est est un navigateur sans interface graphique (on dit "headless") permettant d'exécuter du JavaScript dans une console afin de le tester (ndr. en s'appuyant sur Jasmine et Karma). Un navigateur sans IHM est un navigateur ultra-rapide pour faire tourner du JS (sous-entendu parfait pour avoir des phases de run de TU rapides durant les builds). Le principal défaut de PhantomJS est qu'à la mi 2017 et depuis quelques mois, le projet n'est presque plus actif. Cependant, la maturité actuelle est largement suffisante pour les projets qui démarrent.
TypeScript : C'est à la fois un langage mais également le compilateur de ce langage. Il est développé par notre estimable Microsoft. Dans l'idée, TypeScript permet de coder dans une syntaxe fortement typée, orienté objets & fonctionnelle (ie. avec des classes, des namespaces, des accesseurs, des lambdas, etc) et de transpiler ce code fortement typé en du JavaScript ; autrement dit on convertir le code TypeScript rédigé dans une syntaxe cohérente et fortement typée, vers du JS, c'est-à-dire une syntaxe pas toujours cohérente et faiblement typée. Le gain est d'éviter les pièges de JavaScript qui réclame un niveau d'expertise extraordinaire pour les éviter.
Webpack : Webpack peut quasiment tout faire à l'aide de ses plugins mais l'idée ici est de s'en servir pour trois choses :
- Packager l'ensemble du JS dans un seul et unique fichier (appelé bundle).
- Minifier ce fichier packagé (ainsi que les CSS).
- Ne pas inclure dans le package minifié le code mort, c'est-à-dire les classes qui ne sont jamais chargées directement ou transitivement depuis le fichier JS principal (Main).
Il est bon de rappeler que Webpack est porté par Facebook et ReactJS.
Yarn : NPM c'est top, mais il possède deux inconvénients :
- NPM ne sait pas mettre les paquets dans un répo local (comme le fait a contrario Maven), donc NPM passe son temps à retélécharger les dépendances qu'il a déjà téléchargées pour le projet précédent.
- NPM ne gère pas le build concurrent (il n'est pas multi-threadé) donc le build rame (enfin tout est relatif).
Yarn est un outil qui répond à ces trois problématiques avec un chat tout mimi en guise de logo.