Fermer

octobre 22, 2020

Comment regrouper un site statique simple à l'aide de Webpack


Webpack s'est imposé comme un élément indispensable de la chaîne d'outils JavaScript. Il possède plus de 55 000 étoiles sur GitHub et est utilisé par de nombreux grands acteurs du monde JavaScript, tels que React et Angular.

Cependant, vous n'avez pas besoin d'utiliser un framework frontal ou de travailler sur un projet d'envergure pour en profiter. Webpack est avant tout un bundler, et en tant que tel, vous pouvez également l'utiliser pour regrouper à peu près n'importe quelle ressource ou actif auquel vous voulez penser.

Dans cet article, je vais vous montrer comment installer et configurer webpack, puis utilisez-le pour créer des ensembles minifiés pour un site statique simple avec une poignée d'actifs.

Mais pourquoi voudriez-vous faire cela?

Bonne question. Heureux que vous ayez posé la question!

Une des raisons pour cela est de minimiser le nombre de requêtes HTTP que vous faites au serveur. Au fur et à mesure que la page Web s'agrandit, vous incluerez probablement jQuery (oui, il est toujours populaire en 2020 ), quelques polices, quelques plugins, ainsi que diverses feuilles de style et votre propre code JavaScript . Si vous faites une demande réseau pour chacun de ces éléments, les choses s'additionnent rapidement et votre page peut devenir lente. Le regroupement de votre code peut contribuer à atténuer ce problème.

Webpack facilite également la réduction de votre code, en réduisant davantage sa taille, et il vous permet d'écrire vos ressources dans la saveur que vous désirez. Par exemple, dans cet article, je vais vous montrer comment faire transpiler le JavaScript moderne de Webpack vers ES5. Cela signifie que vous pouvez écrire du JavaScript en utilisant la syntaxe la plus récente et la plus à jour (bien que cela ne soit peut-être pas encore totalement pris en charge), puis servir les navigateurs ES5 qui fonctionneront presque partout.

Et enfin, c'est un exercice d'apprentissage amusant . Que vous utilisiez ou non l'une de ces techniques dans vos propres projets dépend de vous, mais en suivant vous aurez une bonne compréhension de ce que fait le Webpack, comment il le fait et si c'est un bon choix pour vous.

Mise en route

La première chose dont vous aurez besoin est d'installer Node et npm sur votre ordinateur. Si vous n’avez pas encore Node, vous pouvez soit le télécharger à partir du site Web de Node soit le télécharger et l’installer à l’aide d’un gestionnaire de version . Personnellement, je préfère de loin cette deuxième méthode, car elle vous permet de basculer entre plusieurs versions de Node et elle annule un tas d'erreurs d'autorisations, qui pourraient autrement vous voir installer des packages Node avec des droits d'administrateur.

Nous aurons également besoin d'un projet squelette avec lequel travailler. En voici une que j'ai créée plus tôt . Pour le faire fonctionner sur votre machine, vous devez cloner le projet depuis GitHub et installer les dépendances:

 git  clone https://github.com/sitepoint-editors/webpack-static-site-example
 cd  exemple de webpack-static-site
 npm   install 

Ceci installera jQuery plus Slick Slider et Lightbox2 – deux plugins que nous utiliserons sur le site – dans un dossier node_modules à la racine du projet.

Ensuite, vous pouvez ouvrir index.html dans votre navigateur et naviguer sur le site. Vous devriez voir quelque chose comme ceci:

 Notre site statique

Si vous avez besoin d'aide pour l'une des étapes ci-dessus, pourquoi pas rendez-vous sur nos forums et postez une question

Présentation de Webpack au projet

La prochaine chose que nous devrons faire est d'installer webpack. Nous pouvons le faire avec la commande suivante:

 npm   install  webpack webpack-cli --save-dev

Cela installera webpack et la CLI webpack et les ajoutera à la section devDependency de votre fichier package.json :

 "devDependencies" :   {
   "webpack" :   "^ 5.1.3" 
   "webpack-cli" :   "^ 4.0.0" 
} [19659014] Ensuite, nous allons créer un dossier  dist  qui contiendra notre JavaScript fourni: 
 mkdir  dist

Nous pouvons maintenant essayer d'exécuter webpack à partir de la ligne de commande pour voir s'il est configuré correctement:

 ./ node_modules / webpack / bin / webpack.js ./src/js/main.js --output- filename  =  bundle.js --mode  =  développement

Ce que nous faisons ici, c'est demander à Webpack de regrouper le contenu de src / js / main.js dans dist / bundle.js . Si tout est installé correctement, vous devriez voir quelque chose comme cette sortie sur la ligne de commande:

 asset bundle.js  1.04  KiB  [ emitted ]   ( nom: main ) 
./src/js/main.js  192  octets  [ construit ]   [ code généré ] 
webpack  5.1  .3 compilé avec succès  dans   45  ms

Et webpack créera un fichier bundle.js dans le dossier dist . Si vous regardez ce fichier dans l'éditeur de texte de votre choix, vous verrez un tas de passe-partout et le contenu de main.js en bas.

Automatisation de notre configuration

Si nous devions taper tout ce qui précède dans le terminal à chaque fois que nous voulions exécuter webpack, ce serait assez ennuyeux. Créons donc un script npm que nous pouvons exécuter à la place.

Dans package.json modifiez la propriété scripts pour qu'elle ressemble à ceci:

 " scripts ":   {
  " test ":  " echo  "Erreur: aucun test spécifié " && exit 1 "
  " build " ]:   "webpack ./src/js/main.js --output-filename = bundle.js --mode = development" 
} 

Remarquez comment nous pouvons laisser de côté le chemin vers le module Webpack, car lorsqu'il est exécuté à partir d'un script, npm recherchera automatiquement le module dans le dossier node_modules . Maintenant, lorsque vous exécutez npm run build la même chose devrait se produire comme avant. Cool, hein?

Créer un fichier de configuration Webpack

Remarquez comment nous transmettons le chemin du fichier à regrouper et le chemin du fichier de sortie comme arguments à Webpack? Eh bien, nous devrions probablement changer cela et les spécifier dans un fichier de configuration à la place. Cela nous facilitera la vie lorsque nous utiliserons les chargeurs plus tard.

Créez un fichier webpack.config.js à la racine du projet:

 touch  webpack.config.js

Et ajoutez le code suivant:

 module .  exports   =   {
  entrée :   './ src / js / main.js' 
  mode :   'développement' 
  sortie :   {
chemin :   ` $ { __ dirname }  / dist `  
nom de fichier :   'bundle.js' 
  } 
} ; 

Et changez le script npm comme suit:

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

In webpack.config. js nous exportons un objet de configuration, qui spécifie le point d'entrée, le mode webpack devrait s'exécuter dans (plus à ce sujet plus tard), et l'emplacement de sortie du bundle. Relancez tout et tout devrait toujours fonctionner comme avant.

Y compris le bundle

Maintenant que nous avons webpack qui génère un bundle pour nous, la prochaine chose que nous devons faire est de l'inclure quelque part. Mais d'abord, créons un point d'entrée différent, afin que nous puissions répertorier les éléments que nous voulons que Webpack regroupe pour nous. Ce sera un fichier nommé app.js dans le répertoire src / js :

 touch  src / js / app.js

Ajouter ce qui suit à app.js :

  require  ( './ main.js' ) ; 

And changez la configuration du webpack comme suit:

 entry :   './ src / js / app.js' 

Run npm run build à nouveau pour recréer le bundle . Tout devrait fonctionner comme avant.

Maintenant, si vous jetez un œil à index.html vous remarquerez qu'il ne se passe pas grand-chose en JavaScript. Au bas du fichier, nous incluons jQuery et un fichier appelé main.js qui est chargé d'afficher plus d'informations lorsque vous cliquez sur le lien En savoir plus… .

Let's éditez index.html pour inclure le bundle au lieu de main.js . Regardez au bas du fichier. Vous devriez voir:

     < script   src  =  " ./ node_modules / jquery / dist / jquery.min.js "   >  </  script > 
	 < script   src  =  " ./ src / js / main.js "  >  </  script > 
   </  body > 
 </  html >  [19659014] Remplacez ceci par: 
     < script   src  =  " ./ node_modules / jquery / dist / jquery.min.js "  [19659029]>  </  script > 
	 < script   src  =  " ./ dist / bundle.js "  >  </  script > 
   </  body > 
 </  html >  [19659014] Actualisez la page dans le navigateur et assurez-vous que le lien  En savoir plus…  

Regroupement de jQuery

Ensuite, ajoutons jQuery au bundle. Cela réduira le nombre de requêtes HTTP effectuées par la page. Pour ce faire, nous devons modifier le fichier app.js comme ceci:

  window .  $   =   require  ([19659102] 'jquery' ) ; 
 require  ( './ main.js' ) ; 

Ici, nous avons besoin de jQuery, mais comme nous l'avons installé en utilisant npm, nous n'avons pas besoin d'inclure le chemin complet. Nous ajoutons également son alias habituel $ à l'objet global window afin qu'il soit accessible par d'autres scripts. Nous avons besoin de main.js après jQuery, car le premier dépend du second, et l'ordre est important.

Alter index.html pour supprimer la balise de script jQuery: [19659112] <

script
src = " ./ dist / bundle.js " >
</ script [19659029]>
</ body >
</ html >

Run npm run build et encore une fois, actualiser la page du navigateur pour vous assurer que le lien En savoir plus… fonctionne toujours. Cela fait? Bien!

Mesurer nos progrès

C’est bien beau de parler de performances, mais cela ne signifie pas grand-chose si vous n’établissez pas une sorte de métrique mesurable. Dans notre cas, nous essayons de réduire le nombre de requêtes HTTP effectuées par le navigateur et nous pouvons les afficher à partir des outils de développement du navigateur. J'utiliserai Chrome comme exemple de procédure, mais le principe est le même pour tous les navigateurs modernes.

Appuyez sur la touche F12 pour ouvrir les outils de développement, puis assurez-vous que le L'onglet Réseau est sélectionné. Ensuite, cliquez et maintenez le symbole de rechargement à côté de la barre d'adresse (le cercle avec une flèche) et sélectionnez Vider le cache et recharger dur . Vous devriez voir quelque chose de similaire à l'image ci-dessous.

 Les outils de développement Chrome affichant le nombre de requêtes réseau

Comme vous pouvez le voir dans la barre en bas de la fenêtre, huit requêtes sont en cours made (nous en avons déjà réduit une en ajoutant jQuery à notre bundle) et un total de 557 Ko sont transférés sur le fil.

Regroupement du CSS

En regardant index.html le la seule autre chose pour laquelle nous faisons une demande réseau est le CSS. Comme vous pouvez le voir, nous incluons main.css en haut de la page, et ce fichier importe à son tour quatre autres fichiers CSS.

Bien que dans sa configuration standard, le webpack ne puisse que traiter avec JavaScript, nous pouvons utiliser quelque chose appelé un chargeur pour qu'il regroupe également notre CSS. Extrait de la documentation Webpack :

Les chargeurs sont des transformations qui sont appliquées au code source d'un module. Ils vous permettent de prétraiter les fichiers lorsque vous les importez ou les «chargez». Ainsi, les chargeurs sont un peu comme des «tâches» dans d'autres outils de construction et fournissent un moyen puissant de gérer les étapes de construction frontales. Les chargeurs peuvent transformer des fichiers d'un autre langage (comme TypeScript) en JavaScript ou charger des images intégrées en tant qu'URL de données. Les chargeurs vous permettent même d’effectuer des opérations comme importer des fichiers CSS directement à partir de vos modules JavaScript!

Modifions donc app.js :


 require  ( '../ css / main.css' ) ; 


 window .  $   =   require [19659029] ( 'jquery' ) ; 
 require  ( './ main.js' ) ; 

Et nous devons modifiez webpack.config.js pour lui indiquer quel chargeur exécuter lorsqu'il rencontre un fichier se terminant par .css :

 module .  exports   =   {
   ... 
  module :   {
règles :   [
	   {
test :   /  .  css  $  /  
utilisez :   [
		   'style-loader' 
		   'css-loader' 
		] 
	  } [19659231]] 
  } 
} ; 

Comme vous pouvez le voir, j'ai spécifié deux chargeurs: css-loader et style-loader . Des deux, css-loader transforme le CSS en module JavaScript et style-loader injecte le CSS exporté par le module JavaScript dans une balise

Maintenant, exécutons à nouveau webpack en utilisant npm run build et voyons ce qui se passe:

 >  Webpack-static-site-example@1.0.0 build / home / jim / Téléchargements / webpack-static-site-example
>  Webpack

asset bundle.js  349  Kio  [ emitted ]   ( name: main ) 
modules d'exécution  931  octets  4  modules
modules par chemin ./src/  356  Kio
  modules par chemin ./src/css/*.css  3.96  KiB  6  modules
  modules par chemin ./src/js/*.js  294  octets
./src/js/app.js  102  octets  [ construit ]   [ code généré ] 
./src/js/main.js  192  octets  [ construit ]   [ code généré ] 
  ./src/fonts/open-sans/OpenSans-ExtraBold.ttf  352  KiB  [ built ]   [ code généré ] [19659025] [ 1  erreur ] 
modules par chemin ./node_modules/  290  Kio
  modules par chemin ./node_modules/css-loader/dist/runtime/*.js  2,38  Kio
./node_modules/css-loader/dist/runtime/api.js  1.57  KiB  [ built ]   [ code généré ] 
./node_modules/css-loader/dist/runtime/getUrl.js  830  octets  [ built ]   [ code généré ] 
  ./node_modules/jquery/dist/jquery.js  281  KiB  [ construit ]   [ code généré ] 
  ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js  6.67  KiB  [ built ]   [ code generated ]  ]

ERREUR  dans  ./src/fonts/open-sans/OpenSans-ExtraBold.ttf  1 : 0
Échec de l'analyse du module: caractère inattendu  ''   ( 1 : 0 ) 
Vous aurez peut-être besoin d'un chargeur approprié pour gérer ce type de fichier  actuellement aucun chargeur n'est configuré pour traiter ce fichier. Voir https://webpack.js.org/concepts
 ( Code source omis  pour  ce fichier binaire  ) 
 @ ./node_modules/css-loader/dist/cjs.js[19459031</font>![19459018Often/src/css/fontscss 4 : 0-86  6 : 73 -102
 @ ./node_modules/css-loader/dist/cjs.js[19459031</font>![19459018Often/src/css/maincss 3 : 0-104  8 : 26 -59
 @ ./src/css/main.css  2 : 12-89  9 : 17-24  13 : 15-29
 @ ./src/js/app.js  2 : 0-26

webpack  5.1  .3 compilé avec  1  error  in   292  ms

Oh non! Il a explosé. En examinant la sortie, il semble qu'il y ait eu une erreur dans src / css / fonts.css . Si vous ouvrez ce fichier et regardez la ligne 5, vous verrez que nous incluons une police personnalisée ( src / fonts / open-sans / OpenSans-ExtraBold.ttf ) et que webpack ne sait pas que faire avec.

Mais ne vous inquiétez pas, nous l'avons! Nous avons juste besoin d'utiliser un autre chargeur. Cette fois, il s'agit de url-loader qui peut convertir des éléments tels que des polices et des images en URL de données qui peuvent ensuite être ajoutées au bundle:

 module . [19659066] exportations   =   {
   ... 
  module :   {
règles :   [
	   {
test :   /  .  css  $  /  
utilisez :   [
		   'style-loader' 
		   'css-loader' 
		] 
	  } [19659217] {
test :   /  .  ttf  $  /  
utilisez :   [
		   'url-loader' 
		] 
	  } 
	] 
  } [19659029]
} ; 

Et bien sûr, nous devons l'installer:

 npm   install  url-loader --save-dev

La compilation devrait maintenant être exécutée. Testez les choses en supprimant la balise CSS de index.html en recréant l'ensemble et en actualisant la page.

Regroupement de bibliothèques tierces

Maintenant, tournons notre attention sur photos.html . Il se passe un peu plus sur cette page, car nous utilisons deux bibliothèques - Slick Slider et Lightbox2 - qui reposent toutes deux sur jQuery. Heureusement, nous pouvons appliquer les techniques que nous avons apprises pour les inclure dans le bundle.

Alter app.js comme ceci:


 require  ( 'slick-carrousel / slick / slick.css' ) ; 
 require  ( 'slick-carrousel / slick / slick- theme.css ') ; 
 require  (' lightbox2 / dist / css / lightbox.min.css ') ; 
 require [19659029] ( '../ css / main.css' ) ; 


 window .  $   =   require  ( 'jquery' ) ; 
 window .  slick   =   require  ( 'slick-carrousel' )  ; 
 window .  lightbox   =   require  ( 'lightbox2' ) ; 
 require  ( './main.js'[19659029[/19659029)[19659029);[19659014] Supprimez également l'inclusion CSS de l'en-tête du document et l'inclusion du script dans le pied de page. Cela devrait nous donner: 

 < html   lang  =  " en "  > 
   < head [19659029]> 
	 < meta   charset  =  " UTF-8 "  > 
	 < title  >  I Can Haz Cheeseburger?  </  title > 
   </  head > 
   < body > 
...

 < script   src  =  " dist / bundle.js "  >  </  script [19659029]> 
	 < script >   
 $  ( '. Slick-slider' ) .  slick  ( {
points :   vrai 
flèches :   false 
infini :   vrai 
vitesse :   500 
fondu :   vrai 
cssEase :   'linear' 
	  } ) ; 
  </  script > 
   </  body > 
 </  html >  

Bien que là ne serait rien pour nous empêcher d'inclure le code d'initialisation Slick dans le bundle, je vais le laisser sur cette page, car nous voulons seulement l'utiliser ici.

Maintenant, exécutons webpack et voyons ce qui se passe:

  .. .

ERREUR  dans  ./node_modules/slick-carousel/slick/ajax-loader.gif  1 : 7
Échec de l'analyse du module: caractère inattendu  ''   ( 1 : 7 ) 
Vous aurez peut-être besoin d'un chargeur approprié pour gérer ce type de fichier  actuellement aucun chargeur n'est configuré pour traiter ce fichier. Voir https://webpack.js.org/concepts
 ( Code source omis  pour  ce fichier binaire  ) 
 @ ./node_modules/css-loader/dist/cjs.js[19459031</font>![19459018Often/node_modules/slick-carousel/slick/slick-themecss 4 : 0-62  10 : 73-102
 @ ./node_modules/slick-carousel/slick/slick-theme.css  2 : 12-83  9 : 17-24  13 : 15-29
 @ ./src/js/app.js  3 : 0-47

 ..  .. 

Oh non, beaucoup plus d'erreurs! Cette fois, il semble y avoir un problème avec le fichier slick-theme.css qui fait référence à une image au format GIF. Webpack ne sait pas quoi faire avec le GIF, il lève les bras et cesse de fonctionner. Mais nous savons quoi faire, non?

Remplacez la deuxième règle de webpack.config.js par la suivante:

  {
  test :   /  .  ( svg  |  gif  |  png  |  eot  |  woff  |  ttf )  $  /  
  utilisez :   [
	 'url-loader' 
  ] 
} 

Vous remarquerez que j'ai modifié l'expression régulière pour correspondre à plusieurs autres types de fichiers. Ceux-ci sont tous requis par Slick ou par Lightbox2. Exécutez à nouveau webpack et assurez-vous qu'il se termine sans erreur.

Relancez la commande build, actualisez la page et assurez-vous que tout fonctionne.

Quelques touches finales

Nous avons presque terminé, mais il y en a quelques des choses que nous pouvons améliorer.

Gérez le flash du contenu non stylisé

Si vous essayez ceci sur un serveur (le simple fait d'ouvrir le fichier dans votre navigateur ne fonctionnera probablement pas), vous remarquerez un flash de contenu sans style lorsque la page se charge. Reproduisons-le localement.

Commencez par installer le package http-server globalement sur votre système:

 npm   install  -g http-server

Accédez ensuite à la racine du projet et exécutez la commande suivante:

 http-server

Cela démarrera un serveur HTTP sur votre PC. Accédez à http://127.0.0.1:8080 et vous verrez le site comme avant. Ensuite, accédez à l'onglet Réseau des outils de développement de votre navigateur et localisez le menu permettant de limiter la vitesse de votre connexion. Sélectionnez un préréglage Fast 3G (ou équivalent), puis actualisez la page. Vous verrez comment le HTML se charge, puis le CSS est appliqué une seconde ou deux après cela. Evidemment, ce n'est pas optimal.

Remarque: la simulation d'une connexion lente devrait être possible dans tous les navigateurs modernes. Voici des instructions sur la façon de procéder dans Chrome et voici comment le faire dans Firefox .

Une façon de résoudre ce problème consiste à tirer parti de la bloquant la nature des balises et en déplaçant l'inclusion en haut du fichier.


 < html   lang  =  " en "  [19659029]> 
   < head > 
	 < meta   charset  =  " UTF-8 "  [19659029]> 
	 < title >  I Can Haz Cheeseburger?  </  title > 
	 < script   src  =  " dist / bundle.js "  >  </  script > 
   </  head > 
   < corps > 
...
   </  body > 
 </  html >  

Cela fonctionne, mais il faut maintenant plusieurs secondes pour que le site se charge, ce qui aussi n'est pas parfait.

Nous pouvons améliorer quelque peu cette situation en extrayant le CSS dans son propre bundle et en le chargeant en haut de la page tandis que le bundle JavaScript reste là où il est en bas. Nous aurons besoin du mini-css-extract-plugin pour cela, alors installons-le d'abord:

 npm   install  --save-dev mini-css-extract-plugin

Puis modifiez webpack.config.js comme ceci:

  const   MiniCssExtractPlugin   =   require  ( 'mini-css- extract-plugin ') ; 

module .  exportations   =   {
  entrée :   './ src / js / app.js' 
  mode :   'développement' 
  sortie :   {
chemin :   ` $ { __ dirname }  / dist `  
nom de fichier :   'bundle.js' 
  } 
  plugins :   [ nouveau   MiniCssExtractPlugin  () ] 
  module :   {
règles :   [
	   {
test :   /  .  css  $  /  
utilisez :   [
		   MiniCssExtractPlugin .  loader 
		   'css-loader' 
		] 
	  } [19659029]
	   {
test :   /  .  ( svg  |  gif  |  png  |  eot  |  woff  |  ttf )  $  /  
utilisez :   [
		   'url-loader' 
		] 
	  } 
	] 
  } [19659029]
} ; 

Ici, nous avons besoin de notre nouveau plugin en haut du fichier et l'ajoutons au tableau plugins avant de remplacer le chargeur de style par le chargeur du MiniCssExtractPlugin. Désormais, lorsque vous exécutez npm run build deux bundles seront générés dans le dossier dist - bundle.js et main.css .

Modifiez index.html et photos.html pour les inclure comme suit:


 < html   lang  =  " en  " > 
   < head > 
	 < meta   charset  = "  UTF -8  " > 
	 < title >  I Can Haz Cheeseburger?  </  title > 
	 <  link   rel  =  " stylesheet "    href  =  " ./ dist / main.css  " > 
   </  tête > 
   < corps > 
...
 < script   src  =  " ./ dist / bundle.js "  >  </  script > 

 < script >     $  ( '. Slick-slider' ) .  slick  ( {  ...  } ) ;    </  script > 
   </  body > 
 </  html >  

Maintenant, nous évitons le FOUC et le site se charge quelques secondes plus vite, ce qui est certainement un progrès.

Différents lots pour différentes pages

Vous avez peut-être remarqué que nous incluons tous nos éléments dans nos deux lots et que nous diffusons ces lots, quelle que soit la page visitée par un utilisateur. À proprement parler, si un utilisateur ne visite que la page d'index, il n'a pas besoin de télécharger les styles et le code du curseur sur la page de photos.

Selon jusqu'où vous voulez aller dans cette approche, il serait tout à fait possible de créer des lots séparés pour la page de photos et pour les autres pages du site. To do this, you’d use the HtmlWebpackPluginwhich simplifies creation of HTML files to serve your webpack bundles.

Unfortunately, this technique is slightly outside the scope of this tutorial, but you can find an excellent guide on how to do this here.

Minify the Bundles

If you’re going with the one-bundle-for-everything approach, an easy win is to run webpack in production mode, which will see it output a smaller, minified bundle.

To do this, alter webpack.config.js like so:

module.exports = {
  entry: './src/js/app.js',
  mode: 'production',
  ...
};

Now when you run the build command, webpack will output a minified and optimized bundle. This brings the size of bundle.js down from 821.8kB to 485.9kB. Not bad, all things considered.

If you’ve decided to split your bundles into JavaScript and CSS, things get a bit more complicated. To optimize the CSS, we’ll need an extra plugin — optimize-css-assets-webpack-plugin. To use this, we’ll have to override webpack’s default minimizerwhich in turn means we’ll need to specify a JavaScript minimizer, too. For this task, the terser-webpack-plugin is a good choice.

Let’s install both of these:

npm install --save-dev optimize-css-assets-webpack-plugin terser-webpack-plugin

Then alter webpack.config.js like so:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  entry: './src/js/app.js',
  mode: 'production',
  output: {
	path: `${__dirname}/dist`,
	filename: 'bundle.js',
  },
  plugins: [new MiniCssExtractPlugin()],
  module: {
	rules: [
	  {
		test: /.css$/,
		use: [
		  MiniCssExtractPlugin.loader,
		  'css-loader',
		],
	  },
	  {
		test: /.(svg|gif|png|eot|woff|ttf)$/,
		use: [
		  'url-loader',
		],
	  },
	],
  },
  optimization: {
	minimize: true,
	minimizer: [
	  new TerserPlugin({
		extractComments: false,
	  }),
	  new OptimizeCssAssetsPlugin(),
	],
  },
};

Looking at the code, you can see that we’re requiring our two new plugins at the top of the file and that we’ve added an optimization key to the exported configuration object. This allows us to specify Terser as a minimizer for the JavaScript and the Optimize CSS Assets plugin as a minimizer for the CSS. Now when you run npm run buildtwo minimized bundles should be output.

This reduces the bundle sizes from 446.6kB and 338.8kB to 144kB and 336kB respectively. Bundles totaling 480kB might seem a bit excessive for some CSS, JS and a few other assets, but bear in mind that 222kB of that is the font.

Transpile ES6 to ES5

You could also install the babel-loader and have webpack run JavaScript files through that, thus transpiling modern JavaScript to ES5:

npm install --save-dev @babel/core babel-loader @babel/preset-env

Then define a new rule for Javascript files in webpack.config.js:

{
  test: /.js$/,
  exclude: /(node_modules|bower_components)/,
  use: {
	loader: 'babel-loader',
	options: {
	  presets: ['@babel/preset-env'],
	},
  },
},

Now when you run npm run buildJavaScript files will be piped through Babel and thus converted into ES5 syntax which will run in almost any browser.

Of course, you could swap out Babel for almost any other compile-to-JavaScript language you fancy. For example, here’s a TypeScript loader which would enable you to add TypeScript to your projects.

Conclusion

So there you have it. In this article, I’ve demonstrated how to use webpack to bundle a simple static site — a process that reduces the amount of HTTP requests made, thereby making the site potentially snappier and more responsive. I’ve also demonstrated how to have webpack minify the resultant bundles, thus reducing the file size, and how to transpile modern JavaScript to ES5 using the babel-loader.

But before I sign off, let’s compare our original configuration to what we ended up with. Taking index.html as an example, the page originally made nine requests and had a payload of 319kB. Using the Fast 3G preset in Chrome, the page took 4.14s to load. In contrast, using the two-bundle setup, the page makes two requests, has a payload of 472kB, and takes 4.34s to load.

Hmmm … that might leave you wondering why you’d bother with any of this after all. However, don’t forget that both bundles are cached by the browser, so when you then visit the photos page, the original setup has to fetch all of the slider code from the server and needs 6.5 seconds to fully load. The bundled setup already has much of what it needs and is ready in 3.32 seconds.

Even if this strategy isn’t for everyone, hopefully by following along you’ve gained an insight into what webpack does and how it does it. And for those that wish to explore webpack further, I recommend “A Beginner’s Guide to Webpack”, which goes considerably more in-depth on some important concepts, such as the webpack dev server, which will introduce you to the wonderful world of hot module reloading.




Source link