Comme nous l'avons vu plus tôt, Webpack est un bundler, il va vous permettre de compiler votre code et de tout packager en un seul fichier, mais ça ne s'arrête pas là !
Webpack peut aussi gérer vos ressources (images, styles css, etc.) avec ce qu'on appelle des loaders, et il va vous permettre de gérer différentes phases que nous avons vues lors de l'optimisation : bundler, minifier et transpiler.
Préparation du terrain
Une fois que vous avez exécuté npm init
dans votre répertoire pour initialiser votre projet avec NPM, nous pouvons mettre en place les outils.
Installation de Webpack
Pour installer Webpack, il suffit d'exécuter cette commande :
npm install webpack webpack-cli --save-dev
Projet de base
Pour ce chapitre, nous allons partir sur une base de code très simple. Voici les fichiers dont nous allons avoir besoin :
project
|- package.json
|- index.html
|- src
|- index.js
|- query.js
Voici le contenu des différents fichiers :
package.json
{
"name": "my-project",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.21.0",
"webpack-cli": "^3.1.2"
},
"dependencies": {
}
}
index.html
<!doctype html>
My project
src="./dist/app.bundle.js"
src/index.js
import retrieveContent from './query.js';
async function showContent() {
try {
const content = await retrieveContent();
let elt = document.createElement('div');
elt.innerHTML = content.join('<br />');
document.getElementsByTagName('body')[0].appendChild(elt);
} catch (e) {
console.log('Error', e);
}
}
showContent();
src/query.js
export default async function retrieveContent() {
const url = "https://baconipsum.com/api/?type=all-meat¶s=2&start-with-lorem=1";
const response = await fetch(url);
return response.json();
}
Compilation du projet avec Webpack
Maintenant que nous avons une base de code, voyons comment compiler notre projet.
Nous allons créer un fichier webpack.config.js
à la racine du projet. C'est le fichier qui servira de configuration à Webpack pour savoir comment il doit compiler notre projet.
webpack.config.js
const path = require('path');
module.exports = {
mode: "production",
entry: {
app: "./src/index.js"
},
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist")
}
};
Ce fichier nous indique principalement que Webpack va se servir de notre ./src/index.js
comme point d'entrée de notre application et bundler notre code dans un fichier final : ./dist/app.bundle.js
( [name]
étant une variable qui sera remplacée ici par app
, car c'est le nom que l'on a indiqué pour notre fichier index.js
).
Avec notre fichier de configuration prêt, il ne nous reste plus qu'à exécuter Webpack. Pour cela, nous allons utiliser une des fonctionnalités de NPM : les commandes.
Nous allons modifier le fichier package.json
pour ajouter dans les "scripts": {....}
la ligne suivante :
"scripts": {
"test": "...",
"build": "webpack"
}
Tout ce qui se trouve dans scripts
peut être exécuté avec la commande npm run <script_name>
. Ainsi, nous pouvons exécuter npm run build
qui va exécuter la commande webpack
.
Pourquoi ne pas exécuter directement la commande webpack
, me direz-vous ? Eh bien, parce qu'en réalité cette application se trouve dans le dossier ./node_modules/.bin/webpack
. Or, l'avantage de NPM est qu'il va automatiquement chercher dans ce dossier pour exécuter des commandes, ainsi on s'épargne le chemin entier (oui, le développeur est bien un fainéant 😊).
Nous pouvons donc compiler un projet avec :
npm run build
Si tout se passe bien, un fichier app.bundle.js
devrait être généré dans le dossier dist/
. Notre projet a bien été packagé en un seul fichier, alors que nous en avions 2 à l'origine (index.js
et query.js
). Alors, par quelle magie est-ce que Webpack a su où aller chercher tous nos fichiers à partir de notre fichier index.js
?
Grâce aux import
et export
. Ces 2 mots clés permettent respectivement d'importer un autre fichier (qui est appelé un module) et d'exporter des choses (fonctions, variables...).
Nous pouvons, en effet, voir que dans notre fichier index.js
, nous avons importé le module query.js
sous le nom retrieveContent
. Et dans notre fichier query.js
, nous pouvons voir que nous avons exporté la fonction retrieveContent
(ce qui la rend disponible à l'import). Ainsi, quand Webpack analyse votre code, il retrouve toutes ces dépendances et se crée un graph en interne afin d'être capable de tout remettre dans l'ordre dans un seul fichier.
Mais ce n'est pas encore suffisant. En effet, nous utilisons async
et await
qui sont apparus dans une version récente de JavaScript que tous les navigateurs ne supportent pas encore. Ainsi, en fonction du navigateur, le code affichera une erreur. De quoi avons-nous besoin alors ? D'un transpiler afin de rendre notre code JavaScript compatible avec les navigateurs les moins récents !
Transpiler avec Babel
Afin d'utiliser Babel, nous allons devoir l'installer. Mais nous aurons aussi besoin d'installer le loader Babel qui permet de l'intégrer à Webpack. Il est en effet possible d'étendre les capacités de Webpack avec des plugins et des loaders.
npm install --save-dev babel-loader @babel/core @babel/preset-env babel-polyfill
Il va falloir ajouter Babel à la configuration de Webpack. Pour cela, il faut y ajouter ce qu'on appelle des rules
. Les rules
sont des règles de Webpack indiquant les loaders à utiliser pour les types de fichiers que l'on souhaite. Cela veut dire que dès que l'on va importer un module dans notre code, Webpack va regarder dans la liste des rules
s'il y en a une qui correspond à ce type de fichier, et il va lui appliquer les loaders qui correspondent.
Dans notre cas, nous voulons exécuter Babel pour tous les fichiers JavaScript de notre projet (sauf ceux qui se trouvent dans le dossier node_modules
, car ce sont les dépendances NPM et nous ne sommes pas censés modifier leur code).
webpack.config.js
const path = require('path');
module.exports = {
mode: "production",
entry: {
polyfill: "babel-polyfill",
app: "./src/index.js"
},
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
}
}
]
}
};
Vous pouvez passer des options aux loaders. Ainsi, pour Babel, vous pourriez lui demander de charger d'autres plugins pour gérer des syntaxes qui ne sont encore que des propositions pour de futures versions de JavaScript. Ici, nous chargeons le preset de base qui va nous permettre de transpiler notre code.
Vous remarquerez aussi que nous avons ajouté une entrée dans l'objet entry
: polyfill: "babel-polyfill"
. Cela veut dire que lorsque nous compilons notre code, deux fichiers vont être générés : notre code depuis notre fichier index.js
et le polyfill de Babel. Le polyfill permet à Babel d'apporter des modifications au code lors de son exécution. Cela peut être nécessaire pour certaines choses, et c'est le cas de async
/ await
. Afin de prendre en compte ce fichier de polyfill, il va falloir mettre à jour le fichier index.html
afin de le charger aussi (avant notre code) :
index.html
<!doctype html>
My project
src="./dist/polyfill.bundle.js"
src="./dist/app.bundle.js"
Avec ça, tous les navigateurs devraient afficher la page et exécuter correctement le code généré par npm run build
.
Webpack serve
Nous avons maintenant un environnement optimisé qui vous permet :
De minifier votre code ;
De packager votre code ;
De séparer très facilement votre code en plusieurs fichiers afin de bien l'organiser ;
D'utiliser très facilement des bibliothèques développées par la communauté grâce à NPM ;
De transpiler votre code pour pouvoir utiliser les versions next gen de JavaScript ;
Que demander de plus ?
Un serveur pour tester votre code et qui recharge automatiquement votre navigateur dès que vous modifiez votre code ?
Alors allons-y ! C'est exactement ce que webpack serve permet de faire.
Il faut tout d'abord installer le module :
npm install webpack-serve --save-dev
Ensuite, je vous conseille d'ajouter une nouvelle commande au fichier package.json
:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start": "webpack serve"
}
start
est une commande un peu spéciale car elle est exécutée avec un simple npm start
(vous noterez l'absence de run
après npm
).
Enfin, webpack serve va considérer que les fichiers générés par Webpack sont à la racine du server, il nous faut donc mettre à jour notre fichier index.html
:
index.html
<!doctype html>
My project
src="/polyfill.bundle.js"
src="/app.bundle.js"
Une fois que tout ça est fait, il suffit de lancer le serveur de développement :
npm start
La commande indique que l'application est disponible à l'adresse http://localhost:8080/. Il suffira de vous y rendre pour voir votre application.
Tant que cette commande est active, toute modification du code source activera Webpack qui recompilera le code automatiquement et rafraîchira le navigateur, montrant ainsi vos modifications.
En résumé
Dans ce chapitre, vous avez appris :
À installer Webpack ;
À configurer Webpack pour votre projet ;
À compiler votre projet ;
À installer Babel pour transpiler votre code ;
À utiliser
webpack serve
pour tester votre application et mettre à jour votre navigateur à chaque modification de votre code.
Conclusion
Ça y est, vous savez tout ce qu'il faut pour travailler dans de bonnes conditions.
Félicitation pour votre travail. Pensez à réaliser le dernier quiz pour valider vos compétences !
Sachez que malgré tout, nous n'avons fait qu'effleurer la surface. Il y a tant de choses possibles, que je vous invite à aller faire un tour dans les différentes documentations des modules que nous avons vus !