Qu’est-ce que Webpack ?
Webpack est un module bundler. À partir d’un ou plusieurs points d’entrée, il suit chaque import pour construire un graphe des modules et des assets de votre application. Il les transforme ensuite et les combine en un petit nombre de bundles que le navigateur peut charger efficacement.
Sorti en 2012, Webpack est devenu la pierre angulaire du build front-end moderne. Vite est désormais le choix par défaut pour les nouveaux projets car il est plus rapide et plus simple, mais Webpack propulse toujours un nombre énorme d’applications en production. Ses concepts — le graphe de dépendances, les loaders, les plugins et le code splitting — constituent le vocabulaire de tous les bundlers qui ont suivi.
Entrée et sortie
Les deux éléments de configuration requis sont le point de départ du graphe et la destination des bundles.
// webpack.config.js
import path from "node:path";
export default {
entry: "./src/index.js",
output: {
path: path.resolve(import.meta.dirname, "dist"),
filename: "[name].[contenthash].js",
clean: true,
},
};
entry est le module de départ. output.filename utilise un hash de contenu afin que les navigateurs puissent mettre les bundles en cache indéfiniment et ne retélécharger que ceux qui ont été modifiés. clean: true supprime les fichiers obsolètes avant chaque build.
Loaders
Par défaut, Webpack ne comprend que le JavaScript. Les Loaders transforment d’autres types de fichiers en modules lorsqu’ils sont intégrés au graphe.
// loaders.js
export default {
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: "ts-loader",
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|woff2)$/,
type: "asset",
},
],
},
};
Une règle possède un test pour définir les fichiers correspondants et un use pour le loader ou les loaders à appliquer. Les loaders s’exécutent de droite à gauche, donc ["style-loader", "css-loader"] analyse d’abord le CSS puis l’injecte dans la page. Webpack 5 propose également des asset modules, qui remplacent les anciens file-loader et url-loader pour les images et les polices.
Plugins
Les plugins étendent le processus de build lui-même. Alors qu’un loader transforme un fichier, un plugin s’insère dans le cycle de vie de la compilation.
// plugins.js
import HtmlWebpackPlugin from "html-webpack-plugin";
import { DefinePlugin } from "webpack";
export default {
plugins: [
new HtmlWebpackPlugin({ template: "./src/index.html" }),
new DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production"),
}),
],
};
Les plugins courants permettent de générer le fichier HTML, de définir des variables d’environnement, de copier des assets statiques, d’analyser la taille du bundle et de nettoyer le dossier de sortie. C’est ici que réside la majeure partie de la puissance — et de la complexité — de Webpack.
Resolve et alias
Les options resolve contrôlent la manière dont les imports sont recherchés.
// resolve.js
export default {
resolve: {
extensions: [".ts", ".tsx", ".js"],
alias: {
"@": path.resolve(import.meta.dirname, "src"),
},
},
};
extensions vous permet d’importer des fichiers sans spécifier l’extension, et alias crée des raccourcis pour éviter que les imports ne soient encombrés de chemins ../../... Le même alias est généralement reproduit dans la configuration TypeScript pour que l’éditeur soit synchronisé avec le bundler.
Code splitting et tree shaking
Deux optimisations dominent les performances en production.
Le code splitting divise le bundle en morceaux (chunks) chargés à la demande. L’import() dynamique est l’outil principal, et splitChunks extrait automatiquement les dépendances partagées.
// split.js
export default {
optimization: {
splitChunks: { chunks: "all" },
},
};
Le tree shaking supprime les exports inutilisés, mais seulement lorsqu’il peut analyser les imports statiquement. Cela implique l’utilisation de modules ES (import/export) plutôt que CommonJS, ainsi que des modules exempts d’effets de bord. Le fait de marquer des packages comme sideEffects: false dans leur package.json permet à Webpack d’élaguer le code de manière agressive.
Le serveur de développement
webpack-dev-server sert le build en développement avec le hot module replacement.
// devServer.js
export default {
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
proxy: [{ context: ["/api"], target: "http://localhost:8787" }],
},
};
historyApiFallback permet le fonctionnement du routage côté client en servant index.html pour les chemins inconnus, et proxy redirige les requêtes API vers votre backend. Le serveur de développement conserve le build en mémoire, ce qui rend les reconstructions rapides.
Quand utiliser Webpack
Webpack reste un choix solide lorsque vous maintenez une application existante, que vous dépendez d’un loader ou d’un plugin spécifique, ou que vous avez besoin de fonctionnalités avancées comme la module federation pour les micro-frontends. Sa configuration est verbeuse, mais elle est également extrêmement puissante et prévisible une fois maîtrisée.
Pour les nouveaux projets, Vite est généralement le meilleur choix par défaut : démarrage plus rapide, configuration simplifiée et API de plugins moderne. Apprendre Webpack reste pertinent car ses concepts sont directement transférables — l’interface de plugins de Vite est compatible avec Rollup et les mêmes notions de graphe, de transformations et de splitting s’appliquent partout.
Bonnes pratiques
- Séparez la configuration en fichiers ou fonctions
common,devetprod. - Utilisez des hashs de contenu dans les noms de fichiers pour le caching à long terme.
- Privilégiez les ES modules pour permettre le tree shaking.
- Isolez les fonctionnalités lourdes à l’aide d’imports dynamiques.
- Marquez les packages sans effets de bord (side-effect-free) pour que le code inutilisé soit supprimé.
- Reflétez
resolve.aliasdans la configuration TypeScript. - Analysez le bundle avec un outil de visualisation lorsqu’il augmente de manière inattendue.
Erreurs courantes
- Tout livrer dans un seul bundle sans jamais faire de code splitting.
- Utiliser CommonJS et se demander pourquoi le tree shaking ne fonctionne pas.
- Placer un loader dans le mauvais ordre et obtenir des erreurs confuses.
- Dupliquer la configuration entre les environnements au lieu de la composer.
- Configurer des alias dans Webpack mais pas dans TypeScript, créant ainsi un conflit avec l’éditeur.
- Ajouter un plugin qui duplique une fonctionnalité native de Webpack 5.
Et après ?
Webpack est le fondement historique des outils de build modernes et reste un choix fiable pour les applications existantes. Comparez-le avec Vite pour vos nouveaux projets, explorez les packages npm qui fournissent des loaders et des plugins, et découvrez comment ces mêmes concepts sont appliqués dans Turborepo pour les builds de monorepos. Ensuite, analysez la configuration Webpack de votre projet et suivez le cheminement d’un fichier, de l’entrée (entry) jusqu’à la sortie (output).