Gardez le contrôle : un guide pour Webpack et React, Pt. 2

Publié: 2022-03-11

Dans la première partie de ce didacticiel React-Webpack, nous avons expliqué comment configurer les chargeurs et effectuer l'optimisation. Maintenant, nous allons aborder des techniques plus avancées liées à des cas d'utilisation de configuration React/Webpack spécifiques.

TypeScript et React avec Webpack : entrez dans Babel

Il existe plusieurs façons d'utiliser TypeScript dans votre projet React. Bien que ts-loader soit une bonne option, j'aimerais me concentrer sur la façon de transpiler TypeScript en utilisant @babel/preset-typescript car de nombreuses bibliothèques publient des plugins Babel pour optimiser le temps de compilation. En plus de traiter les fichiers TypeScript, cela nous permettra d'utiliser des plugins Babel fournis par diverses bibliothèques telles que styled-components ou react-intl.

La première chose à faire est d'installer les dépendances TypeScript et Babel :

 npm install -D typescript @babel/preset-typescript @types/react @types/react-dom

Nous allons ensuite générer un fichier de configuration TypeScript à l'aide du programme en ligne de commande tsc :

 ./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules

La commande ci-dessus générera un tsconfig.json adapté à l'écriture de code pour un environnement de navigateur. L'option --isolatedModules applique certaines contraintes qui garantissent que le code que vous écrivez sera compatible avec @babel/plugin-transform-typescript . Cette option est utile pour que votre IDE vous avertisse lorsque vous écrivez du code d'une manière que Babel ne pourra pas transformer.

Ensuite, nous allons mettre à jour babel.config.js en introduisant un nouveau préréglage :

 @@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",

Et activez l'extension de fichier .ts dans webpack.config.js :

 @@ -11,7 +11,7 @@ module.exports = function(_env, argv) { return { devtool: isDevelopment && "cheap-module-source-map", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "assets/js/[name].[contenthash:8].js", @@ -20,7 +20,7 @@ module.exports = function(_env, argv) { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", @@ -61,6 +61,9 @@ module.exports = function(_env, argv) { } ] }, + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"] + }, plugins: [ isProduction && new MiniCssExtractPlugin({

La configuration ci-dessus est suffisante pour pouvoir transpiler notre code mais elle ne le valide pas réellement. Nous devrons effectuer une vérification de type dans un processus parallèle séparé à l'aide fork-ts-checker-webpack-plugin .

Tout d'abord, nous devons l'installer :

 npm install -D fork-ts-checker-webpack-plugin

Ensuite, nous l'ajouterons à la section plugins dans webpack.config.js :

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -78,6 +79,9 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new ForkTsCheckerWebpackPlugin({ + async: false }) ].filter(Boolean), optimization: {

Spécifier async: false empêchera Webpack d'émettre du code invalide et affichera les erreurs de compilation dans une superposition lors de l'exécution d'un serveur de développement.

Remarque : Vous pouvez également être intéressé par les macros Babel, qui gagnent du terrain.

CSS, amélioré via Webpack

Dans l'article précédent, nous avons couvert le style de base en utilisant css-loader . Il existe plusieurs façons d'améliorer cette configuration.

La configuration proposée tirera parti des technologies CSS Modules, Sass et PostCSS. Bien qu'ils se complètent à certains égards, vous n'avez pas besoin de tous les utiliser en même temps. La configuration finale aura tous les plugins ci-dessus activés, et nous vous laisserons le soin de laisser quelque chose de côté si vous êtes certain que "vous n'en aurez pas besoin".

Modules CSS

Les modules CSS résolvent le problème de la portée globale dans les fichiers CSS en générant un nom aléatoire et unique pour chaque classe CSS. Du point de vue d'un fichier JavaScript consommant un module CSS, une association entre le nom de la classe d'origine et celle randomisée est représentée par un objet exporté par le loader. Il vous permet de trouver et d'utiliser des classes spécifiées dans un fichier CSS d'une manière qui rend les collisions accidentelles presque impossibles.

La prise en charge des modules CSS est déjà incluse dans css-loader . Nous allons maintenant devoir ajouter une nouvelle règle pour préciser quand les modules CSS sont utilisés :

 @@ -33,11 +33,25 @@ module.exports = function(_env, argv) { }, { test: /\.css$/, use: [ isProduction ? MiniCssExtractPlugin.loader : "style-loader", "css-loader" ] }, + { + test: /\.module.css$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + modules: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

Avec cela, tout fichier se terminant par .module.css sera traité avec les modules CSS activés.

PostCSS

PostCSS est un framework de traitement CSS extensible avec une énorme bibliothèque de plugins que vous pouvez utiliser pour étendre la syntaxe CSS, effectuer une optimisation ou fournir des solutions de rechange pour les anciens navigateurs.

Tout d'abord, nous allons installer les dépendances nécessaires :

 npm install -D postcss-loader postcss-import postcss-preset-env

Et mettez à jour notre configuration CSS :

 @@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {

Nous allons configurer PostCSS en utilisant les plugins suivants :

  • postcss-import : permet à PostCSS de traiter les instructions @import
  • postcss-preset-env : applique des polyfills pour prendre en charge les fonctionnalités CSS modernes dans la plupart des navigateurs

Créez un fichier appelé postcss.config.js et remplissez-le avec ce qui suit :

 module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };

Vous pouvez consulter le répertoire du plugin PostCSS pour d'autres extensions que vous pourriez trouver utiles et les ajouter à votre configuration.

Sass/SCSS

Sass est un autre framework de traitement CSS populaire. Contrairement à PostCSS, Sass est livré avec des "piles incluses". Prêt à l'emploi, Sass prend en charge les règles imbriquées, les mixins et les règles de réécriture pour une compatibilité descendante. Alors que PostCSS vise à préserver la syntaxe CSS standard, la syntaxe Sass peut diverger de la spécification CSS. Malgré cela, Sass est une solution tellement omniprésente que son utilisation pour la création de CSS peut être une option plus simple, mais qui dépend de vos besoins.

Tout d'abord, nous allons installer les dépendances nécessaires :

 npm install -D sass-loader node-sass resolve-url-loader

Ensuite, ajoutez un nouveau chargeur à notre configuration Webpack :

 @@ -38,6 +38,25 @@ module.exports = function(_env, argv) { "css-loader" ] }, + { + test: /\.s[ac]ss$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 2 + } + }, + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

Nous avons résolu de manière préventive quelques problèmes avec l'extrait ci-dessus :

  1. Nous avons introduit resolve-url-loader après sass-loader pour que les importations relatives fonctionnent à partir des fichiers @import et Sass.

  2. Nous avons spécifié l'option importLoaders pour que css-loader traite les fichiers @import -ed à l'aide des chargeurs qui le suivent.

Avec la configuration ci-dessus, nous pouvons commencer à créer nos styles en utilisant Sass/SCSS en plus des modules PostCSS et CSS que nous avons décrits précédemment. Bien que toutes ces options puissent être activées simultanément, vous n'êtes pas obligé de toutes les utiliser dans le même projet, vous pouvez donc choisir l'outil qui correspond le mieux à vos besoins.

Travailleurs Web

Les travailleurs Web sont un concept puissant du Web moderne. Il vous permet de décharger des calculs coûteux loin du thread principal. Les travailleurs Web doivent être utilisés avec parcimonie et réservés à des choses qui ne peuvent pas être optimisées autrement par une planification intelligente dans une boucle d'événements. L'utilisation de web workers est un bon candidat pour optimiser les opérations longues et synchrones.

Webpack facilite l'utilisation des travailleurs Web avec worker-loader , qui regroupe les fichiers de travail dans le répertoire de sortie et fournit une classe de travail au fichier consommateur.

Tout d'abord, nous devons installer worker-loader :

 npm install -D worker-loader

Ajoutez-le ensuite à notre fichier de configuration :

 @@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [

Maintenant, tout ce que vous avez à faire pour commencer à utiliser les web workers est d'instancier une classe importée à partir d'un fichier se terminant par .worker.js qui implémente l'API Worker ordinaire.

Travailleurs des services

Les techniciens de service permettent des techniques d'optimisation avancées et des améliorations de l'expérience utilisateur. Ils permettent à votre application de fonctionner hors ligne lorsqu'un utilisateur perd sa connexion réseau. Ils permettent également à votre application de se charger instantanément même après avoir poussé une mise à jour.

Webpack facilite la configuration des service workers pour votre application à l'aide du module workbox-webpack-plugin. Tout d'abord, nous devons l'installer :

 npm install -D workbox-webpack-plugin

Ensuite, nous ajouterons le plugin à la section plugins de notre configuration Webpack :

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -75,6 +76,11 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new WorkboxPlugin.GenerateSW({ + swDest: "service-worker.js", + clientsClaim: true, + skipWaiting: true }) ].filter(Boolean), optimization: {

La configuration ci-dessus utilise les options suivantes :

  • swDest spécifie le nom du fichier de sortie pour le fichier de travail généré.
  • clientsClaim demande au service worker de prendre le contrôle de la page immédiatement après l'enregistrement et de commencer à servir les ressources mises en cache au lieu d'attendre le prochain rechargement de la page.
  • skipWaiting fait en sorte que les mises à jour du service worker prennent effet immédiatement au lieu d'attendre que toutes les instances actives soient détruites.

Il y a une bonne raison pour laquelle les deux dernières options ne sont pas la valeur par défaut. Lorsqu'elles sont activées simultanément, des problèmes peuvent survenir dans des situations urgentes. C'est donc à vous de décider consciemment si vous souhaitez conserver ces options activées dans votre configuration.

Enfin, nous devons enregistrer le service worker lorsqu'un utilisateur ouvre notre application :

 @@ -2,3 +2,9 @@ import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render(<h3>React App</h3>, document.getElementById("root")); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker.register("/service-worker.js"); + }); +}

Les techniciens de service sont capables de bien plus que d'ajouter des fonctionnalités hors ligne à notre application. Si vous avez besoin d'un plus grand contrôle sur le comportement du travailleur de service, vous pouvez utiliser le plug-in InjectManifest à la place. En écrivant votre propre fichier de technicien de service, vous pouvez également activer la mise en cache des demandes d'API et utiliser d'autres fonctionnalités activées par les techniciens de service, telles que les notifications push. Vous pouvez en savoir plus sur les capacités de Workbox dans la section Recettes avancées de sa documentation officielle.

Advanced React Webpack Config : Donner un avantage à votre projet

Cette deuxième partie de notre série de didacticiels Webpack devrait vous avoir fourni les connaissances nécessaires pour étendre votre configuration Webpack au-delà des cas d'utilisation les plus généraux de React. J'espère que vous avez trouvé ces informations utiles et que vous pourrez en toute confiance étendre votre configuration personnalisée pour atteindre les objectifs spécifiques à votre projet.

Comme toujours, vous pouvez trouver les fichiers de configuration complets sur GitHub et vous référer à la documentation Webpack et sa section plugins pour trouver plus de recettes applicables à vos objectifs. Merci pour la lecture!