Si vous avez déjà touché un projet front-end embarquant du Sass, du Less ou encore avec un framework comme Vue.js, Angular ou React, vous avez sans doute déjà croisé ce groupeur de modules (modules bundler) plus connu sous le nom de webpack. Composé d'un ou plusieurs fichiers de configuration, il transforme nos fichiers sources précédemment cités en HTMLHTML (HyperText Markup Language) est un langage permettant de décrire le découpage d'une page web., CSSFeuilles de style qui permettent de mettre en forme des pages web. et JavaScriptLangage de scripting orienté objet minifiés. Mais qu'est-ce donc cette diablerie ?
C'est ce que nous allons essayer de comprendre à travers cet article, car derrière cette magie, se cache un rouage bien ficelé et pas si compliqué à comprendre (car oui rien n'est magique en informatique, sauf les tests unitaires qui passent du premier coup).
Dans cet article, nous découvrirons les concepts de webpack, nous verrons ensuite comment initialiser un projet webpack et enfin un exemple pour compiler du Sass en CSS, mais avant de commencer :
Nous pouvons voir webpack comme une petite usine. En entrée, nous ajoutons nos matières premières brutes (fichiers JavaScript, fichiers de style, images, polices ...). Notre usine prend ensuite ces matières premières et les transforme avec l'aide de différentes machines (loaders ou plugins), ce qui permet de sortir un produit fini qui sont nos assets statiques en HTML, CSS et JavaScript exécutables par n'importe quel navigateur (Internet Explorer je te vois dans le fond de la salle, tu sors).
Cette usine est tout simplement le fichier webpack.config.js et nos machines sont les dépendances ajoutées via le node package manager (npm). Les dépendances peuvent être ajoutées à la guise du développeur, ce qui permet une approche modulaire par rapport aux besoins de l'application.
Pour comprendre webpack, il faut d'abord comprendre ses concepts :
L'entry point, où le point d'entrée en français, spécifie le ou les fichiers qui serviront de "matières premières" à webpack. Avec ces fichiers, il construira ensuite son graphe de dépendances et déterminera ensuite à quels autres modules ou bibliothèques ces points d'entrées sont liés.
Le point d'entrée par défaut est `javascript ./src/index.js
mais nous pouvons très bien spécifier nos points d'entrées différemment comme dans l'exemple ci-dessous :
module.exports = {
entry: {
'./src/styles/app.sass',
'./src/js/app.js',
'./src/index.pug',
}
}
L'output, comme son nom l'indique, signifie la sortie. Cette propriété indique à webpack où nos fichiers doivent être générés et comment il doit les nommer. Par défaut, le chemin configuré est ./public/main.js
pour le fichier principal et tous les autres fichiers sont générés dans ce dossier javascript dist
.
Comme l'entrée, nous pouvons également personnaliser notre sortie, que ce soient les chemins ou les noms des fichiers :
const path = require('path');
module.exports = {
entry: ...,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'mon-app.bundle.js',
},
};
Ici, nous rentrons dans le noyau dur de webpack, le module et les loaders. Ce sont les machines qui vont permettre de traiter nos "matières premières". En dehors du bloc module, webpack comprend seulement le JavaScript et le JSON. Les loaders lui permettent de traiter d'autres types de fichiers et de les convertir en fichiers compréhensibles par l'application (en JavaScript) et donc de pouvoir ensuite l'ajouter à son graphe de dépendances.
Le bloc module contient un bloc rules qui requiert un tableau d'objets contenant 2 propriétés : test et use.
En fonction des loaders utilisés, des paramètres peuvent être obligatoire, il faudra alors se référer à la documentation du loader en question. Ci-dessous, un exemple de loader qui a pour rôle de sortir un fichier CSS minifié. Nous pouvons d'ailleurs voir que cette règle n'est applicable qu'aux fichiers CSS.
module.exports = {
entry: ...,
output: ...,
module: {
rules: [
{
test: /\.css$/,
loader: 'css-loader',
options: {
minimize: true,
},
}
],
},
};
La liste des loaders disponibles
Alors que les loaders sont utilisés pour transformer certains types de fichier, les plugins permettent de réaliser un plus large panel d'actions comme de l'optimisation, la gestion d'assets ou encore la gestion d'environnements de travail. Le loader ne peut traiter que du JavaScript, le plugin permet donc de réaliser ce qu'un loader ne peut pas faire !
Un plugin est un objet JavaScript qui possède une méthode apply. Une fois instanciée (cf. exemple ci-dessous), cette méthode est ensuite appelée par le compilateur de webpack, lui donnant ainsi accès à l'intégralité du cycle de vie de la compilation.
Comme les loaders, voici une liste des plugins disponibles. La réponse est donc à peu prêt tout ! 😅 Mais comme une démonstration est toujours plus parlante que du blabla, prenons l'exemple du plugin Copy qui permet tout simplement de copier un fichier ou l'intégralité d'un dossier vers le dossier de build final (ou ailleurs si nous voulons).
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
entry: ...,
output: ...,
module: ...,
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
]
})
]
};
Nous en parlons depuis le début, mais qu'est-ce que le graphe de dépendances ? Le graphe de dépendances est un graphe orienté qui indique comment les modules sont interconnectés entre eux. webpack va, dans un premier temps, analyser les modules qui sont présents et réaliser son propre graphe à partir des modules importés dans le fichier de configuration. Ce graphe regroupe ensuite tous ces modules en un petit nombre de bundle (simplification au maximum) pour qu'il puisse être chargé par le navigateur de manière optimale.
Rien de bien compliqué pour initialiser un projet webpack. Seul node.js est requis sur le poste de travail pour pouvoir démarrer.
Une fois notre dossier de projet créé, nous pouvons ouvrir un terminal et taper :
npm init -y
Cette commande va créer et initialiser notre fichier package.json. Le projet initialisé, nous pouvons maintenant taper la commande suivante qui va installer webpack sur notre projet :
npm install webpack webpack-cli --save-dev
Créons maintenant l'arborescence de fichiers suivante :
webpack-demo
+ |- package.json
+ |- /dist
+ |- bundle.js
+ |- index.html
+ |- webpack.config.js
+ |- /src
+ |- index.js
Une fois nos fichiers créés, nous pouvons rédiger notre fichier de configuration webpack webpack.config.js
pour que celui-ci ressemble à cela :
const webpack = require("webpack");
const path = require("path");
let config = {
mode: 'development',
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "./bundle.js"
}
}
module.exports = config;
À travers ce fichier de configuration, nous spécifions l'environnement de notre projet avec l'option mode : 'development', notre fichier d'entrée qui est notre index.js et enfin notre fichier de sortie situé dans le dossier dist./dist/bundle.js.
Ensuite, pour automatiser la compilation de nos fichiers, nous allons nous rendre dans notre fichier package.json et nous allons spécifier le script suivant :
"scripts": {
"watch": "webpack --watch"
},
Enfin, nous n'avons plus qu'à lancer notre script dans une console à travers la commande suivante et webpack va automatiquement écouter nos fichiers sources pour les compiler à chaque modification :
npm run watch
Et c'est fini 😁 Quoi c'est tout ?! Notre usine est terminée oui, maintenant libre à vous d'ajouter les modules qui vous conviennent pour compiler du Sass ou des assets par exemple !
Mais, comme nous sommes sympa chez AXOPEN, nous allons tout de même vous donner un exemple de configuration pour compiler des fichiers Sass en CSS, la base quoi ! 😎
Pour commencer, ajoutons un dossier sass
avec un fichier bundle.scss
à notre dossier source. Nous devrions avoir l'arborescence suivante :
webpack-demo
+ |- package.json
+ |- /dist
+ |- bundle.js
+ |- index.html
+ |- webpack.config.js
+ |- /src
+ |- /sass
+ | - bundle.scss
+ |- index.js
Il faut ensuite ajouter les dépendances suivantes à notre projet :
npm install file-loader sass-loader sass --save-dev
Une fois nos dépendances installées, nous pouvons configurer notre fichier webpack.config.js :
Nous spécifions une deuxième entrée pour notre fichier Sass
entry: [
"./src/index.js",
"./src/sass/bundle.scss"
],
Nous ajoutons enfin nos deux loaders pour effectuer la transformation
module: {
rules: [
{
test: /\.scss$/i,
use: [
{
loader: 'file-loader',
options: {
name: 'css/bundle.css',
}
},
// Compile le Sass en CSS
"sass-loader"
],
},
],
}
Attention, l'ordre des loaders est très important ! En effet, les loaders sont exécutés de la fin vers le début, c'est pour cela que le sass-loader se trouve en dernière position. Le Sass est d'abord transformé en CSS puis le résultat est ensuite transvasé dans le fichier de sortie qui est le bundle.css.
Enfin plus qu'à lancer notre commande npm run watch et tester notre configuration :
body {
background-color: red;
font-style: italic;
div{
background-color: purple;
}
}
Vous devriez avoir le résultat suivant dans votre fichier CSS :
body {
background-color: red;
font-style: italic;
}
body div {
background-color: purple;
}
Et voilà, notre compilateur Sass est en place ! Libre à vous ensuite d'ajouter des plugins de minification pour optimiser au mieux vos assets ! 👌
Et vous, que pensez-vous de webpack ?
Pourquoi et comment écrire des tests unitaires ? Définition et implémentation dans une application Java Springboot
Explication du fonctionnement de Callback queue & Event loop en Javascript.
On vous explique la création de A à Z d’une application ReactJS avec API SpringBoot, avec création et déploiement sur AWS (S3, CloudFront, EC2, ECS, RDS, ELB) et CI/CD GitLab - 4/4