Fermer

avril 25, 2018

Guide d'initiation à Webpack 4 et au regroupement de modules –


Le document Webpack 4 docs indique que:

Webpack est un regroupeur de modules. Son but principal est de regrouper les fichiers JavaScript pour les utiliser dans un navigateur, mais il est également capable de transformer, grouper ou empaqueter n'importe quelle ressource ou ressource.

Webpack est devenu l'un des outils les plus importants pour les utilisateurs modernes. développement web. Il s'agit principalement d'un bundler de module pour votre JavaScript, mais il peut être enseigné pour transformer tous vos éléments frontaux tels que HTML, CSS, voire des images. Il peut vous donner plus de contrôle sur le nombre de requêtes HTTP que votre application effectue et vous permet d'utiliser d'autres caractéristiques de ces ressources (Pug, Sass et ES8, par exemple). Webpack vous permet également de consommer facilement des paquets de npm.

Cet article s'adresse aux nouveaux utilisateurs de Webpack et couvre l'installation initiale, la configuration, les modules, les chargeurs, les plugins, le découpage de code et le remplacement de modules chauds. Si vous trouvez les didacticiels vidéo utiles, je peux vous recommander fortement le Webpack de Glen Maddern de First Principles comme point de départ pour comprendre ce qui rend Webpack spécial. C'est un peu vieux maintenant, mais les principes sont toujours les mêmes, et c'est une excellente introduction.

Pour suivre à la maison, vous devrez avoir installé Node.js . Vous pouvez également télécharger l'application de démo de notre repo GitHub .

 Une machine webpack 4 qui compresse tous les éléments web

Setup

Nous allons initialiser un nouveau projet avec npm et installer webpack et webpack-cli :

 mkdir webpack-démo && cd webpack-demo
npm init -y
npm installer --save-dev webpack webpack-cli

Ensuite, nous allons créer la structure et le contenu du répertoire suivant:

   webpack-demo
  | - package.json
+ | - webpack.config.js
+ | - / src
+ | - index.js
+ | - / dist
+ | - index.html

dist / index.html



  
     Bonjour Webpack 
  
  
     

src / index.js

 const racine = document.createElement ("div")
root.innerHTML = `

Bonjour Webpack.

` document.body.appendChild (racine)

webpack.config.js

 const path = require ('chemin')

module.exports = {
  entrée: './src/index.js',
  sortie: {
    nom de fichier: "http://www.sitepoint.com/bundle.js",
    chemin: path.resolve (__ dirname, 'dist')
  }
}

Ceci demande à Webpack de compiler le code dans notre point d'entrée src / index.js et de sortir un paquet dans /dist/bundle.js . Ajoutons un script npm pour exécuter Webpack.

package.json

   {
    ...
    "scripts": {
- "test": "echo " Erreur: aucun test spécifié  "&& exit 1"
+ "develop": "webpack --mode développement --watch",
+ "build": "webpack - production de mode"
    },
    ...
  }

En utilisant la commande npm run nous pouvons créer notre premier paquet!


bundle.js 2.92 KiB principal [emitted] main

Vous devriez maintenant pouvoir charger dist / index.html dans votre navigateur et être accueilli par "Hello Webpack".

Ouvrir dist / bundle.js à voir ce que Webpack a fait. En haut se trouve le code d'amorçage du module de Webpack, et tout en bas se trouve notre module. Vous n'êtes peut-être pas encore impressionné par la couleur, mais si vous êtes arrivé si loin, vous pouvez commencer à utiliser ES Modules, et Webpack sera capable de produire un bundle pour la production qui fonctionnera dans tous les navigateurs.

Ctrl + C et exécutez npm run build pour compiler notre bundle en mode de production .

 Taille de bloc Morceaux
bundle.js 647 octets principal [emitted] main

Notez que la taille de l'ensemble est descendue de 2,92 KiB à 647 octets .

Jetez un autre regard sur dist / bundle.js et vous verra un désordre de code laid. Notre bundle a été minifié avec UglifyJS: le code fonctionnera exactement de la même manière, mais avec la plus petite taille de fichier possible

  • - le développement en mode optimise la vitesse de construction et le débogage
  • - production en mode optimise la vitesse d'exécution au moment de l'exécution et la taille du fichier de sortie.

Modules

En utilisant les modules ES, vous pouvez diviser vos grands programmes en plusieurs petits programmes autonomes

. comment consommer des modules ES en utilisant les instructions import et export . Par exemple, essayons cela maintenant en installant lodash-es et en ajoutant un second module:

 npm install --save-dev lodash-es

src / index.js

 import {groupBy} à partir de "lodash-es"
importer des personnes de "./people"

const managerGroups = groupBy (personnes, "manager")

const root = document.createElement ("div")
root.innerHTML = `
 $ {JSON.stringify (managerGroups, null, 2)} 

`
document.body.appendChild (racine)

src / people.js

 const personnes = [
  {
    manager: "Jen",
    name: "Bob"
  },
  {
    manager: "Jen",
    name: "Sue"
  },
  {
    manager: "Bob",
    name: "Shirley"
  }
]

exporter les personnes par défaut

Exécutez npm run développez pour démarrer Webpack et actualiser index.html . Vous devriez voir un tableau de personnes groupées par directeur imprimé à l'écran.

Note: Les importations sans chemin relatif comme 'es-lodash' sont des modules de npm installés à / node_modules . Vos propres modules auront toujours besoin d'un chemin relatif comme './ people' car c'est ainsi que vous pouvez les différencier.

Notez dans la console que la taille de notre bundle a augmenté à 1,41 Mio ! Cela vaut la peine d'être surveillé, même si dans ce cas il n'y a pas lieu de s'inquiéter. En utilisant npm run build pour compiler en mode production tous les modules de lodash inutilisés de lodash-es sont retirés du bundle. Ce processus de suppression des importations inutilisées s'appelle tree-shaking et c'est quelque chose que vous obtenez gratuitement avec Webpack.

> npm run develop

Nombres de morceaux de morceaux de taille d'actif
bundle.js 1.41 MiB principal [emitted]  [big]   main
> npm run build

Nombres de morceaux de morceaux de taille d'actif
bundle.js 16,7 KiB 0 [emitted] main

Chargeurs

Les chargeurs vous permettent d'exécuter des préprocesseurs sur les fichiers lors de leur importation. Cela vous permet de regrouper des ressources statiques au delà de JavaScript mais regardons ce qui peut être fait en chargeant les modules .js en premier

Gardons notre code moderne en exécutant tout ] .js via le transtypeur JavaScript de prochaine génération Babel :

 npm install --save-dev "babel-loader@x8.0.0-beta" @ babel / core @babel / preset-env

webpack.config.js

   const path = require ('chemin')

  module.exports = {
    entrée: './src/index.js',
    sortie: {
      nom de fichier: "http://www.sitepoint.com/bundle.js",
      chemin: path.resolve (__ dirname, 'dist')
    },
+ module: {
+ règles: [
+       {
+         test: /.js$/,
+         exclude: /(node_modules|bower_components)/,
+         use: {
+           loader: 'babel-loader',
+         }
+       }
+     ]
+}
  }

.babelrc

 {
  "préréglages": [
    ["@babel/env", {
      "modules": false
    }]
  ],
  "plugins": ["syntax-dynamic-import"]
}

Cette configuration empêche Babel de transférer des déclarations import et export dans ES5, et autorise les importations dynamiques – que nous verrons plus loin dans la section sur la division des codes.

Nous sommes maintenant libres d'utiliser les fonctionnalités de langage moderne, et ils seront compilés à ES5 qui fonctionne dans tous les navigateurs.

Sass

Les chargeurs peuvent être enchaînés en une série de transformations. Un bon moyen de démontrer comment cela fonctionne est d'importer Sass depuis notre JavaScript:

 npm install --save-dev style-loader css-loader sass-loader noeud-sass

webpack.config.js

   module.exports = {
    ...
    module: {
      règles: [
        ...
+       {
+         test: /.scss$/,
+         use: [{
+           loader: 'style-loader'
+         }, {
+           loader: 'css-loader'
+         }, {
+           loader: 'sass-loader'
+         }]
+}
      ]
    }
  }

Ces chargeurs sont traités dans l'ordre inverse:

  • sass-loader transforme Sass en CSS
  • css-loader parse le CSS en JavaScript et résout les dépendances.
  • style-loader génère notre CSS dans une balise
    dans le document.

Vous pouvez les considérer comme des appels de fonction. La sortie d'un chargeur se charge comme entrée dans le suivant:

 styleLoader (cssLoader (sassLoader ("source")))

Ajoutons un fichier source Sass et importons un module.

src / style.scss

 $ bluegrey: # 2b3a42;

pré {
  rembourrage: 8px 16px;
  arrière-plan: $ bluegrey;
  couleur: # e1e6e9;
  font-family: Menlo, Courrier, monospace;
  taille de police: 13px;
  hauteur de ligne: 1,5;
  text-shadow: 0 1px 0 rgba (23, 31, 35, 0,5);
  border-radius: 3px;
}

src / index.js

   import {groupBy} à partir de 'lodash-es'
  importer des personnes de './people'

+ importer './style.scss'

  ...

Redémarrez la construction avec Ctrl + C et npm run développez . Actualiser index.html dans le navigateur et vous devriez voir un peu de style

CSS dans JS

Nous venons d'importer un fichier Sass de notre JavaScript, comme un module.

Ouvrir ] dist / bundle.js et recherchez "pre {". En effet, notre Sass a été compilé en une chaîne de CSS et enregistré en tant que module dans notre bundle. Lorsque nous importons ce module dans notre JavaScript, style loader génère cette chaîne dans une balise

  

Commençons un serveur à partir du répertoire dist pour le voir en action:

 cd dist
service npx

Ouvrez http: // localhost: 5000 dans le navigateur et voyez ce qui se passe. Seul bundle.js est récupéré initialement. Lorsque le bouton est cliqué, le module de chat est importé et initialisé.

 Requêtes réseau montrant un chargement paresseux de morceaux

Avec très peu d'effort, nous avons ajouté le découpage dynamique à notre application.

Plugins

Bien que les loaders utilisent des transformations sur des fichiers uniques, les plugins fonctionnent sur de plus gros morceaux de code. 19659004] Maintenant que nous regroupons notre code, les modules externes et actifs statiques, notre paquet va croître - rapidement . Les plugins sont là pour nous aider à diviser notre code de manière intelligente et à optimiser les choses pour la production.

Sans le savoir, nous avons déjà utilisé beaucoup de plugins Webpack par défaut avec "mode"

développement

  • Fournit process.env.NODE_ENV avec la valeur "développement"
  • NamedModulesPlugin

production

  • Fournit processus.env. NODE_ENV avec la valeur "production"
  • UglifyJsPlugin
  • ModuleConcatenationPlugin
  • NoEmitOnErrorsPlugin

Production

Avant d'ajouter des plugins supplémentaires, nous allons d'abord scinder notre config afin que nous puissions appliquer des plugins spécifiques à chaque environnement.

Renommez webpack.config.js en webpack.common.js et ajoutez un fichier de configuration pour le développement et la production.

 - | - webpack.config.js
+ | - webpack.common.js
+ | - webpack.dev.js
+ | - webpack.prod.js

Nous allons utiliser webpack-merge pour combiner notre config commune avec la config spécifique à l'environnement:

 npm install --save-dev webpack-merge

webpack.dev.js

 const merge = require ('webpack-merge')
const common = require ('./ webpack.common.js')

module.exports = fusion (commun, {
  mode: 'développement'
})

webpack.prod.js

 const merge = require ('webpack-merge')
const common = require ('./ webpack.common.js')

module.exports = fusion (commun, {
  mode: 'production'
})

package.json

   "scripts": {
- "develop": "webpack --watch --mode développement",
- "build": "webpack - production de mode"
+ "develop": "webpack --watch --config webpack.dev.js",
+ "build": "webpack --config webpack.prod.js"
   },

Maintenant, nous pouvons ajouter des plugins spécifiques au développement dans webpack.dev.js et des plugins spécifiques à la production dans webpack.prod.js .

Split CSS

C'est Considéré comme la meilleure pratique pour séparer votre CSS de votre JavaScript lors du regroupement pour la production en utilisant ExtractTextWebpackPlugin .

Les chargeurs .scss actuels sont parfaits pour le développement, donc nous les déplacerons de webpack.common.js dans webpack.dev.js et ajoutez ExtractTextWebpackPlugin à webpack.prod.js uniquement.

 npm install --save-dev extract-text-webpack-plugin@4.0.0-beta.0

webpack.common.js

   ...
  module.exports = {
    ...
    module: {
      règles: [
        ...
-       {
-         test: /.scss$/,
-         use: [
-           {
-             loader: 'style-loader'
-           }, {
-             loader: 'css-loader'
-           }, {
-             loader: 'sass-loader'
-           }
-         ]
-},
        ...
      ]
    }
  }

webpack.dev.js

   const merge = require ('webpack-merge')
  const common = require ('./ webpack.common.js')

  module.exports = fusion (commun, {
    mode: 'développement',
+ module: {
+ règles: [
+       {
+         test: /.scss$/,
+         use: [
+           {
+             loader: 'style-loader'
+           }, {
+             loader: 'css-loader'
+           }, {
+             loader: 'sass-loader'
+           }
+         ]
+}
+]
+}
  })

webpack.prod.js

   const merge = require ('webpack-merge')
+ const ExtractTextPlugin = require ('extrait-text-webpack-plugin')
  const common = require ('./ webpack.common.js')

  module.exports = fusion (commun, {
    mode: 'production',
+ module: {
+ règles: [
+       {
+         test: /.scss$/,
+         use: ExtractTextPlugin.extract({
+           fallback: 'style-loader',
+           use: ['css-loader', 'sass-loader']
+})
+}
+]
+},
+ plugins: [
+     new ExtractTextPlugin('style.css')
+   ]
  })

Comparons la sortie de nos deux scripts de construction:

> npm run develop

Nombres de morceaux de morceaux de taille d'actif
Application app.bundle.js 28.5 KiB [emitted]
chat.bundle.js 1.4 KiB chat [emitted] chat
> npm run build

Nombres de morceaux de morceaux de taille d'actif
chat.bundle.js 375 octets 0 [emitted] chat
app.bundle.js 1,82 KiB 1 [emitted] application
style.css 424 octets 1 [emitted] application

Maintenant que notre CSS est extrait de notre bundle JavaScript pour la production, nous devons le à partir de notre HTML.

dist / index.html

   
  
    
      
       Séparation de code 
+ 
    
    
           
  

Cela permet un téléchargement parallèle du CSS et du JavaScript dans le navigateur, ce qui accélérera le chargement d'un seul paquet. Il permet également aux styles d'être affichés avant que le JavaScript ne finisse de télécharger.

Générer du HTML

Chaque fois que nos sorties ont changé, nous avons dû mettre à jour index.html pour référencer les nouveaux chemins de fichiers . C'est précisément ce que html-webpack-plugin a été créé pour nous automatiquement

Nous pouvons aussi ajouter clean-webpack-plugin en même temps pour effacer notre / dist répertoire avant chaque build.

 npm installer --save-dev html-webpack-plugin nettoyer-webpack-plugin

webpack.common.js

   const path = require ('chemin')
+ const CleanWebpackPlugin = require ('clean-webpack-plugin');
+ const HtmlWebpackPlugin = require ('html-webpack-plugin');

  module.exports = {
    ...
+ plugins: [
+     new CleanWebpackPlugin(['dist']),
+ nouveau HtmlWebpackPlugin ({
+ titre: 'Mon application de tueur'
+})
+]
  }

Maintenant chaque fois que nous construisons, dist sera effacé. Nous allons maintenant voir la sortie index.html avec les bons chemins vers nos bundles d'entrée

Running npm run develop produit ceci:



  
    
     My killer app  ]
  
  
       

Et npm run build produit ceci:



  
    
     My killer app 
    
  
    

Développement

Le webpack-dev-server vous fournit un simple serveur web et vous donne rechargement en direct vous n'avez donc pas besoin d'actualiser manuellement la page pour voir les modifications.

 npm install --save-dev webpack-dev-server

package.json

   {
    ...
    "scripts": {
- "develop": "webpack --watch --config webpack.dev.js",
+ "develop": "webpack-dev-server --config webpack.dev.js",
    }
    ...
  }
> npm run développer

「「 wds 」: Le projet s'exécute à http: // localhost: 8080 /
「「 wds 」: la sortie webpack est desservie à partir de /

Ouvrez http: // localhost: 8080 / dans le navigateur et modifiez l'un des fichiers JavaScript ou CSS. Vous devriez le voir construire et actualiser automatiquement.

HotModuleReplacement

Le plugin HotModuleReplacement va plus loin que Live Reloading et échange des modules à l'exécution sans l'actualiser . Une configuration correcte permet d'économiser beaucoup de temps lors du développement d'applications à une seule page. Lorsque vous avez beaucoup d'état dans la page, vous pouvez apporter des modifications incrémentielles aux composants, et seuls les modules modifiés sont remplacés et mis à jour.

webpack.dev.js

 + const webpack = require ('webpack')
  const merge = require ('webpack-merge')
  const common = require ('./ webpack.common.js')

  module.exports = fusion (commun, {
    mode: 'développement',
+ devServer: {
+ chaud: vrai
+},
+ plugins: [
+     new webpack.HotModuleReplacementPlugin()
+   ],
    ...
  }

Maintenant, nous devons accepter changer les modules de notre code pour réinitialiser les choses.

src / app.js

 + if (module.hot) {
+ module.hot.accept ()
+}

  ...

Note: Lorsque le remplacement de module chaud est activé, module.hot est réglé sur true pour le développement et false pour la production, donc ceux-ci sont

Redémarrez le build et voyez ce qui se passe quand nous faisons ce qui suit:

  • Cliquez Ouvrir le chat
  • Ajouter une nouvelle personne au .js module
  • Cliquez Ouvrez à nouveau le chat .

Voici ce qui se passe:

  1. Quand Ouvrir chat est cliqué, le Le module chat.js est récupéré et initialisé
  2. HMR détecte quand people.js est modifié
  3. module.hot.accept () dans index.js provoque le remplacement de tous les modules chargés par ce bloc d'entrée
  4. Lorsque Clavardage ouvert est de nouveau cliqué, chat.init () est exécuté avec le code de la mise à jour mo dule.

CSS Replacement

Changeons la couleur du bouton en rouge et voyons ce qui se passe:

src / app.scss

   button {
    ...
- arrière-plan: # 24b47e;
+ arrière-plan: rouge;
    ...
  }

Nous pouvons maintenant voir des mises à jour instantanées de nos styles sans perdre aucun état. C'est une expérience de développeur beaucoup améliorée!

HTTP / 2

L'un des principaux avantages de l'utilisation d'un bundler de modules tel que Webpack est qu'il peut vous aider à améliorer les performances en vous donnant le contrôle sur la façon dont les assets sont construits puis récupéré sur le client. Il a été considéré meilleure pratique pour les années à concaténer les fichiers afin de réduire le nombre de demandes qui doivent être faites sur le client. Ceci est toujours valide, mais HTTP / 2 permet maintenant de livrer plusieurs fichiers dans une seule requête donc la concaténation n'est plus une solution miracle. Votre application peut réellement bénéficier de la mise en cache individuelle de nombreux petits fichiers. Le client pourrait alors aller chercher un seul module modifié plutôt que d'avoir à récupérer un paquet entier avec principalement le même contenu.

Le créateur de Webpack, Tobias Koppers a écrit un poste informatif expliquant pourquoi le regroupement est toujours important, même dans l'ère HTTP / 2

En savoir plus à ce sujet à Webpack & HTTP / 2 .

Plus à vous

J'espère que vous J'ai trouvé cette introduction à Webpack utile et je peux commencer à l'utiliser avec beaucoup d'efficacité. Cela peut prendre un peu de temps pour se familiariser avec la configuration, les chargeurs et les plugins de Webpack, mais apprendre comment fonctionne cet outil sera payant.

La documentation de Webpack 4 est en cours de préparation, mais elle est très bien préparée. Je vous recommande fortement de lire les Guides Concepts et pour plus d'informations. Voici quelques autres sujets qui pourraient vous intéresser:

Webpack 4 est-il le bundler de votre choix? Faites-moi savoir dans les commentaires ci-dessous.






Source link