Webpack: un guide du débutant





Bonne journée, mes amis!



Je vous présente une traduction de l'article "Webpack: Une introduction douce" de Tyler McGinnis.



Avant d'explorer une nouvelle technologie, posez-vous deux questions:



  1. Pourquoi cet outil est-il nécessaire?
  2. Quelles tâches effectue-t-il?


Si vous ne pouvez pas répondre à ces questions, vous n'aurez peut-être pas besoin de la technologie que vous étudiez. Essayons de répondre à ces questions par rapport à Webpack.



Pourquoi avez-vous besoin d'un pack Web?



Webpack est un constructeur de modules. Il analyse les modules de l'application, crée un graphe de dépendances, puis assemble les modules dans le bon ordre en un ou plusieurs bundles, qui peuvent être référencés par le fichier "index.html".



App.js ->       |
Dashboard.js -> | Bundler | -> bundle.js
About.js ->     |


Quels problèmes le Webpack résout-il?



Habituellement, lors de la création d'une application JavaScript, le code est divisé en plusieurs parties (modules). Ensuite, dans le fichier "index.html", vous devez spécifier un lien vers chaque script.



<body>

    ...
    
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="libs/react.min.js"></script>
    <script src='src/admin.js'></script>
    <script src='src/dashboard.js'></script>
    <script src='src/api.js'></script>
    <script src='src/auth.js'></script>
    <script src='src/rickastley.js'></script>
</body>


Ce n'est pas seulement fastidieux, mais également sujet aux erreurs. Il est important non seulement de ne pas oublier les scripts, mais également de les organiser dans le bon ordre. Si vous chargez un script qui dépend de React avant de charger React lui-même, votre application s'arrêtera. Webpack résout ces problèmes. Pas besoin de s'inquiéter d'inclure tous les scripts dans l'ordre.



<body>

    ...
    
    <script src='dist/bundle.js'></script>
</body>


Comme nous l'apprendrons bientôt, la collecte de modules n'est qu'un aspect du fonctionnement d'un pack Web. Si nécessaire, vous pouvez forcer le webpack à effectuer certaines transformations de module avant de les ajouter au bundle. Par exemple, la conversion de SASS / LESS en CSS standard ou de JavaScript moderne en ES5 pour les navigateurs plus anciens.



Installer un pack Web



Après avoir initialisé le projet avec npm, pour que le webpack fonctionne, vous devez installer deux packages - webpacket webpack-cli.



npm i webpack webpack-cli -D


webpack.config.js



Après avoir installé ces packages, le webpack doit être configuré. Pour ce faire, un fichier est créé webpack.config.jsqui exporte l'objet. Cet objet contient les paramètres du pack Web.



module.exports = {}


La tâche principale d'un webpack est d'analyser les modules, de les transformer éventuellement et de les combiner intelligemment en un ou plusieurs bundles, le webpack doit donc connaître trois choses:



  1. Point d'entrée de l'application
  2. Conversions à effectuer
  3. Où placer le bundle généré


Point d'entrée



Quel que soit le nombre de modules qu'une application contient, il y a toujours un point d'entrée unique. Ce module comprend le reste. En règle générale, ce fichier est index.js. Cela pourrait ressembler à ceci:



index.js
  imports about.js
  imports dashboard.js
    imports graph.js
    imports auth.js
      imports api.js


Si nous indiquons au webpack le chemin d'accès à ce fichier, il l'utilise pour créer le graphe de dépendance de l'application. Pour ce faire, vous devez ajouter une propriété entryaux paramètres du pack Web avec la valeur du chemin d'accès au fichier principal:



module.exports = {
    entry: './app/index.js'
}


Conversion avec des chargeurs



Après avoir ajouté le point d'entrée, vous devez informer le Webpack des transformations à effectuer avant de générer le bundle. Pour cela, des chargeurs sont utilisés.



Par défaut, lors de la génération de graphiques de dépendances basés sur l'opérateur, le import / require()webpack ne peut traiter que les fichiers JavaScript et JSON.



import auth from './api/auth' // 
import config from './utils/config.json' // 
import './styles.css' // ️
import logo from './assets/logo.svg' // ️


Il est peu probable que vous osiez vous limiter aux fichiers JS et JSON dans votre application, vous aurez probablement également besoin de styles, de SVG, d'images, etc. C'est là que les chargeurs entrent en jeu. La tâche principale des chargeurs, comme leur nom l'indique, est de permettre au Webpack de fonctionner avec plus que des fichiers JS et JSON.



La première étape consiste à installer le chargeur. Puisque nous voulons charger SVG, utilisez npm pour installer svg-loader.



npm i svg-inline-loader -D 


Ensuite, ajoutez-le aux paramètres du pack Web. Tous les chargeurs sont inclus dans un tableau d'objets module.rules:



module.exports = {
    entry: './app/index.js',
    module: {
        rules: []
    }
}


Les informations sur le chargeur se composent de deux parties. Le premier est le type de fichiers en cours de traitement ( .svgdans notre cas). Le second est le chargeur utilisé pour traiter ce type de fichier ( svg-inline-loaderdans notre cas).



module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' }
    ]
  }
}


Nous pouvons maintenant importer des fichiers SVG. Mais qu'en est-il de nos fichiers CSS? Pour les styles utilisés css-loader.



npm i css-loader -D 


module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: 'css-loader' }
    ]
  }
}


Nous pouvons maintenant importer des fichiers SVG et CSS. Cependant, pour que nos styles fonctionnent correctement, nous devons ajouter un autre chargeur. Grâce à css-loadernous, nous pouvons importer des fichiers CSS. Mais cela ne veut pas dire qu'ils seront inclus dans le DOM. Nous souhaitons non seulement importer de tels fichiers, mais également les placer dans une balise <style>afin qu'ils s'appliquent aux éléments DOM. Pour cela, vous avez besoin style-loader.



npm i style-loader -D 


module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
    ]
  }
}


Notez que puisque deux chargeurs sont utilisés pour traiter les fichiers CSS, la valeur de la propriété useest un tableau. Faites également attention à l'ordre des chargeurs, d'abord style-loader, ensuite css-loader. C'est important. Le webpack les appliquera dans l'ordre inverse. Il est d'abord utilisé css-loaderpour les importations './styles.css', puis style-loaderpour l'injection de styles dans le DOM.



Les chargeurs peuvent être utilisés non seulement pour importer des fichiers, mais aussi pour les convertir. Le plus populaire est la conversion de JavaScript de nouvelle génération en JavaScript moderne à l'aide de Babel. Il est utilisé pour cela babel-loader.



npm i babel-loader -D 


module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  }
}


Il existe des chargeurs pour presque tous les types de fichiers.



Point de sortie



Maintenant, le webpack connaît le point d'entrée et les chargeurs. L'étape suivante consiste à spécifier le répertoire du bundle. Pour ce faire, ajoutez une propriété outputaux paramètres du pack Web.



const path = require('path')

module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index_bundle.js'
  }
}


L'ensemble du processus ressemble à ceci:



  1. Le webpack reçoit un point d'entrée situé à ./app/index.js
  2. Il analyse les instructions import / requireet crée un graphe de dépendances
  3. Le webpack commence à créer le bundle en convertissant le code à l'aide des chargeurs appropriés
  4. Il récupère un paquet et le place dans dist/index_bundle.js


Plugins



Nous avons vu comment utiliser des chargeurs pour traiter des fichiers individuels avant ou pendant la génération d'un bundle. Contrairement aux chargeurs, les plugins vous permettent d'effectuer des tâches après la création d'un bundle. Ces tâches peuvent concerner à la fois le bundle lui-même et d'autres codes. Vous pouvez considérer les plugins comme des chargeurs plus puissants et moins limités.



Prenons un exemple.



HtmlWebpackPlugin



La tâche principale d'un webpack est de générer un bundle qui peut être référencé dans index.html.



HtmlWebpackPlugincrée index.htmldans le répertoire avec le bundle et ajoute automatiquement un lien vers le bundle qu'il contient.



Nous avons nommé le bundle index_bundle.jset l' avons placé dist. HtmlWebpackPlugincréera un nouveau fichier index.htmldans le répertoire distet ajoutera un lien vers le bundle qu'il contient - <script src='index_bundle.js'></script>. Génial, non? Puisqu'il est index.htmlgénéré HtmlWebpackPlugin, même si nous changeons le point de sortie ou le nom du bundle, il HtmlWebpackPluginrecevra ces informations et changera le contenu index.html.



Comment utilisons-nous ce plugin? Comme d'habitude, vous devez d'abord l'installer.



npm i html-webpack-plugin -D 


Ensuite, ajoutez la propriété aux paramètres du pack Web plugins.



const path = require('path')

module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index_bundle.js'
  },
  plugins: []
}


Nous créons une instance HtmlWebpackPlugindans un tableau plugins.




const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}


EnvironnementPlugin



Si vous utilisez React, vous souhaiterez lui attribuer process.env.NODE_ENVune valeur productionavant de déployer l'application. Cela permettra à React de construire en production en supprimant les outils de développement tels que les avertissements. Le webpack vous permet de le faire via un plugin EnvironmentPlugin. Il fait partie du pack Web, vous n'avez donc pas besoin de l'installer.



const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')

module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new webpack.EnvironmentPlugin({
      'NODE_ENV': 'production'
    })
  ]
}


Désormais, n'importe où dans notre application, nous pouvons définir le mode de production avec process.env.NODE_ENV.



HtmlWebpackPluginet EnvironmentPluginn'est qu'une petite partie du système de plugins webpack.



Mode (mode)



Lors de la préparation d'une demande de production, plusieurs étapes doivent être suivies. Nous venons d'en couvrir un - la mise process.env.NODE_ENVen valeur production. Une autre action consiste à réduire le code et à supprimer les commentaires pour réduire la taille de l'ensemble.



Il existe des plugins spéciaux pour résoudre ces tâches, mais il existe un moyen plus simple. Dans les paramètres du pack Web, il peut être défini modesur developmentou en productionfonction de l'environnement de développement.



const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './app/index.js',
  module: {
    rules: [
      { test: /\.svg$/, use: 'svg-inline-loader' },
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ],
  mode: 'production'
}


Veuillez noter que nous avons supprimé EnvironmentPlugin. Le fait est qu'après avoir défini modela valeur, le productionwebpack attribue automatiquement la process.env.NODE_ENVvaleur production. Il réduit également le code et supprime les avertissements.



Lancement d'un webpack



Pour le moment, nous savons comment fonctionne le webpack et comment le configurer, il reste à l'exécuter.



Nous avons un fichier package.jsonque nous pouvons créer scriptpour l'exécuter webpack.



"scripts": {
  "build": "webpack"
}


Désormais, lorsque vous exécutez la commande npm run builddans le terminal, un pack Web sera lancé, qui créera un bundle optimisé index_bundle.jset le placera dans dist.



Modes de développement et de production



Dans l'ensemble, nous en avons terminé avec le webpack. Enfin, voyons comment basculer entre les modes.



Lors de la construction pour la production, nous voulons tout optimiser autant que possible. Dans le cas du mode développement, le contraire est vrai.



Pour basculer entre les modes, vous devez créer deux scripts dans package.json.



npm run buildconstruira le bundle de production.



npm run startdémarrera le serveur de développement et surveillera les changements de fichiers.



Si vous vous en souvenez, nous définissons cette modevaleur sur une valeur productiondans les paramètres du pack Web. Cependant, nous n'en avons pas besoin maintenant. Nous voulons que la variable d'environnement ait une valeur appropriée en fonction de la commande exécutée. Changeons le script builddans package.json.



"scripts": {
  "build": "NODE_ENV='production' webpack",
}


Si vous utilisez Windows, la commande serait: "SET NODE_ENV='production' && webpack".



Maintenant, dans les paramètres du pack Web, nous pouvons modifier la valeur en modefonction de process.env.NODE_ENV.



...

  mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
}


Pour créer un bundle prêt à l'emploi pour notre application, nous l'exécutons simplement npm run builddans le terminal. Les distfichiers de répertoire sont créés index.htmlet index_bunlde.js.



Serveur de développement



Lorsqu'il s'agit de développer une application, la vitesse est primordiale. Nous ne voulons pas redémarrer le webpack et attendre une nouvelle version à chaque changement. C'est là que le package est utile webpack-dev-server.



Comme son nom l'indique, il s'agit d'un serveur Webpack pour le développement. Au lieu de créer un répertoire dist, il stocke les données en mémoire et les traite sur un serveur local. De plus, il prend en charge le redémarrage en direct. Cela signifie que toute modification webpack-dev-serverreconstruira les fichiers et redémarrera le navigateur.



Installez le package.



npm i webpack-dev-server -D 


Tout ce qui reste à faire est d' ajouter le script startà package.json.



"scripts": {
  "build": "NODE_ENV='production' webpack",
  "start": "webpack-dev-server"
}


Nous avons maintenant deux commandes: l'une pour démarrer le serveur de développement et l'autre pour créer le bundle fini.



J'espère que l'article vous a été utile. Merci de votre attention.



All Articles