Erste Schritte mit Webpack
Veröffentlicht: 2022-03-10In den frühen Tagen, als die Modularität in JavaScript eingeführt wurde, gab es keine native Unterstützung für die Ausführung von Modulen im Browser. Die Unterstützung für modulare Programmierung wurde in Node.js mithilfe des CommonJS-Blueprints implementiert und von denjenigen übernommen, die JavaScript zum Erstellen serverseitiger Anwendungen verwenden.
Es hatte auch Aussichten für große Webanwendungen, da Entwickler Namespace-Kollisionen vermeiden und besser wartbare Codebasen aufbauen konnten, indem sie Code in einem modulareren Muster schrieben. Aber es gab noch eine Herausforderung: Module konnten nicht innerhalb von Webbrowsern verwendet werden, in denen normalerweise JavaScript ausgeführt wurde.
Um dieses Problem zu lösen, wurden Modul-Bundler wie Webpack, Parcel, Rollup und auch der Closure Compiler von Google geschrieben, um optimierte Bundles Ihres Codes für den Browser Ihres Endbenutzers zum Herunterladen und Ausführen zu erstellen.
Was bedeutet es, Ihren Code zu „bündeln“?
Das Bündeln von Code bezieht sich auf das Kombinieren und Optimieren mehrerer Module zu einem oder mehreren produktionsbereiten Bündeln . Das hier erwähnte Bündel kann besser als Endprodukt des gesamten Bündelprozesses verstanden werden.
In diesem Artikel konzentrieren wir uns auf webpack, ein von Tobias Koppers geschriebenes Tool, das sich im Laufe der Zeit zu einem wichtigen Tool innerhalb der JavaScript-Toolchain entwickelt hat, das häufig in großen und kleinen Projekten verwendet wird.
Hinweis: Um von diesem Artikel zu profitieren, sollten Sie mit JavaScript-Modulen vertraut sein. Außerdem muss Node auf Ihrem lokalen Computer installiert sein, damit Sie Webpack lokal installieren und verwenden können.
Was ist Webpack?
webpack ist ein stark erweiterbarer und konfigurierbarer statischer Modulbundler für JavaScript-Anwendungen. Aufgrund seiner Erweiterbarkeit können Sie externe Ladeprogramme und Plugins anschließen, um Ihr Endziel zu erreichen.
Wie in der Abbildung unten gezeigt, durchläuft webpack Ihre Anwendung von einem Root-Einstiegspunkt aus , erstellt einen Abhängigkeitsgraphen, der aus Abhängigkeiten besteht, die direkt oder indirekt auf die Root-Datei wirken, und erzeugt optimierte Bündel der kombinierten Module.
Um zu verstehen, wie Webpack funktioniert, müssen wir einige der verwendeten Terminologien verstehen (lesen Sie das Webpack-Glossar). Diese Terminologie wird häufig in diesem Artikel verwendet und wird auch häufig in der Webpack-Dokumentation erwähnt.
- Brocken
Ein Chunk bezieht sich auf den aus Modulen extrahierten Code. Dieser Code wird in einer Chunk-Datei gespeichert . Chunks werden häufig verwendet, wenn Code-Splitting mit Webpack durchgeführt wird. - Module
Module sind heruntergebrochene Teile Ihrer Anwendung, die Sie importieren, um eine bestimmte Aufgabe oder Funktion auszuführen. Webpack unterstützt Module, die mit der ES6-, CommonJS- und AMD-Syntax erstellt wurden. - Vermögenswerte
Der Begriff Assets wird häufig in Webpacks und anderen Bundlern im Allgemeinen verwendet. Es bezieht sich auf die statischen Dateien , die während des Erstellungsprozesses gebündelt werden. Diese Dateien können alles sein, von Bildern über Schriftarten bis hin zu Videodateien. Wenn Sie den Artikel weiter unten lesen, werden Sie sehen, wie wir Loader verwenden, um mit verschiedenen Asset-Typen zu arbeiten.
Empfohlene Lektüre : Webpack - Eine ausführliche Einführung
Nachdem wir verstanden haben, was Webpack ist und welche Terminologie es verwendet, sehen wir uns an, wie sie beim Zusammenstellen einer Konfigurationsdatei für ein Demoprojekt angewendet werden.
Hinweis : Sie müssen auch webpack-cli
installiert haben, um webpack auf Ihrem Computer verwenden zu können. Wenn es nicht installiert ist, werden Sie von Ihrem Terminal aufgefordert, es zu installieren.
Webpack-Konfigurationsdateien
Neben der Verwendung des webpack-cli von einem Terminal aus können Sie webpack auch über eine Konfigurationsdatei in Ihrem Projekt verwenden. Aber mit den neueren Versionen von Webpack können wir es in unserem Projekt ohne Konfigurationsdatei verwenden. Wir können webpack
als Wert eines der Befehle in unserer Datei package.json
“ verwenden – ohne Flag. Auf diese Weise geht Webpack davon aus, dass sich die Einstiegspunktdatei Ihres Projekts im src
-Verzeichnis befindet. Es bündelt die Eintragsdatei und gibt sie im dist
-Verzeichnis aus.
Ein Beispiel ist die Beispieldatei package.json
unten. Hier verwenden wir webpack, um die Anwendung ohne Konfigurationsdatei zu bündeln:
{ "name" : "Smashing Magazine", "main": "index.js", "scripts": { "build" : "webpack" }, "dependencies" : { "webpack": "^5.24.1" } }
Wenn Sie den build-Befehl in der obigen Datei ausführen, bündelt webpack die Datei im Verzeichnis src/index.js
und gibt sie in einer main.js
-Datei in einem dist
-Verzeichnis aus. webpack ist jedoch viel flexibler als das. Wir können den Einstiegspunkt ändern , den Ausgabepunkt anpassen und viele andere Standardverhalten verfeinern, indem wir eine Konfigurationsdatei mit dem Flag -- config
bearbeiten.
Ein Beispiel ist der modifizierte Build-Befehl aus der obigen Datei package.json
:
"build" : "webpack --config webpack.config.js"
Oben haben wir das Flag --config
hinzugefügt und eine webpack.config.js
als Datei mit der neuen Webpack-Konfiguration angegeben.
Die Datei webpack.config.js
existiert jedoch noch nicht. Also müssen wir es in unserem Anwendungsverzeichnis erstellen und den folgenden Code unten in die Datei einfügen.
# webpack.config.js const path = require("path") module.exports = { entry : "./src/entry", output : { path: path.resolve(__dirname, "dist"), filename: "output.js" } }
Die obige Datei konfiguriert webpack immer noch, um Ihre JavaScript-Datei zu bündeln, aber jetzt können wir anstelle des von webpack verwendeten Standardpfads einen benutzerdefinierten Eingabe- und Ausgabedateipfad definieren.
Ein paar Dinge, die Sie bei einer Webpack-Konfigurationsdatei beachten sollten:
- Eine Webpack-Konfigurationsdatei ist eine JavaScript-Datei, die als JavaScript-CommonJS-Modul geschrieben ist.
- Eine Webpack-Konfigurationsdatei exportiert ein Objekt mit mehreren Eigenschaften. Jede dieser Eigenschaften wird als Option zum Konfigurieren von Webpack beim Bündeln Ihres Codes verwendet. Ein Beispiel ist die
mode
:-
mode
In der Konfiguration wird diese Option verwendet, um denNODE_ENV
Wert während des Bündelns festzulegen. Es kann entweder einenproduction
oder einendevelopment
haben. Wenn nichts angegeben ist, ist es standardmäßignone
. Es ist auch wichtig zu beachten, dass Webpack Ihre Assets basierend auf demmode
unterschiedlich bündelt. Beispielsweise speichert webpack Ihre Bundles automatisch im Entwicklungsmodus, um die Bundle-Zeit zu optimieren und zu reduzieren. Sehen Sie sich den Modus-Abschnitt der Webpack-Dokumentation an, um ein Änderungsprotokoll der Optionen zu sehen, die automatisch in jedem Modus angewendet werden.
-
Webpack-Konzepte
Bei der Konfiguration von Webpack entweder über die CLI oder über eine Konfigurationsdatei gibt es vier Hauptkonzepte , die als Optionen angewendet werden. Der nächste Abschnitt dieses Artikels konzentriert sich auf diese Konzepte und wendet sie beim Erstellen der Konfiguration für eine Demo-Webanwendung an.
Bitte beachten Sie, dass die unten erläuterten Konzepte einige Ähnlichkeiten mit anderen Modul-Bundlern aufweisen. Wenn Sie beispielsweise Rollup mit einer Konfigurationsdatei verwenden, können Sie ein Eingabefeld definieren, um den Einstiegspunkt des Abhängigkeitsdiagramms anzugeben, ein Ausgabeobjekt, das konfiguriert, wie und wo die produzierten Chunks platziert werden, und auch ein Plugins-Objekt zum Hinzufügen externer Plugins.
Eintrag
Das Eingabefeld in Ihrer Konfigurationsdatei enthält den Pfad zu der Datei, von der aus webpack mit dem Erstellen eines Abhängigkeitsdiagramms beginnt. Von dieser Eingangsdatei geht webpack zu anderen Modulen über, die direkt oder indirekt vom Eingangspunkt abhängen.
Der Einstiegspunkt Ihrer Konfiguration kann ein Einzeleintragstyp mit einem einzelnen Dateiwert sein, ähnlich wie im folgenden Beispiel:
# webpack.configuration.js module.exports = { mode: "development", entry : "./src/entry" }
Der Einstiegspunkt kann auch ein Multi-Main-Eintragstyp mit einem Array sein, das den Pfad zu mehreren Eintragsdateien enthält, ähnlich wie im folgenden Beispiel:
# webpack.configuration.js const webpack = require("webpack") module.exports = { mode: "development", entry: [ './src/entry', './src/entry2' ], }
Ausgabe
Wie der Name schon sagt, befindet sich das erstellte Bundle im Ausgabefeld einer Konfiguration. Dieses Feld ist praktisch, wenn Sie mehrere Module eingerichtet haben. Anstatt den vom Webpack generierten Namen zu verwenden, können Sie Ihren eigenen Dateinamen angeben .
# webpack.configuration.js const webpack = require("webpack"); const path = require("path"); module.exports = { mode: "development", entry: './src/entry', output: { filename: "webpack-output.js", path: path.resolve(__dirname, "dist"), } }
Lader
Standardmäßig versteht webpack nur JavaScript-Dateien innerhalb Ihrer Anwendung. Webpack behandelt jedoch jede als Modul importierte Datei als Abhängigkeit und fügt sie dem Abhängigkeitsdiagramm hinzu. Um statische Ressourcen wie Bilder, CSS-Dateien, JSON-Dateien oder sogar Ihre in CSV gespeicherten Daten zu verarbeiten, verwendet webpack Loader, um diese Dateien in das Bundle zu „laden“.
Loader sind flexibel genug, um für viele Dinge verwendet zu werden, von der Transpilierung Ihres ES-Codes über die Handhabung der Stile Ihrer Anwendung bis hin zum Linting Ihres Codes mit ESLint.
Es gibt drei Möglichkeiten, Loader in Ihrer Anwendung zu verwenden . Eine davon ist die Inline- Methode, indem sie direkt in die Datei importiert wird. Um beispielsweise die Bildgröße zu minimieren, können wir den image-loader
Loader direkt in der Datei verwenden, wie unten gezeigt:
// main.js import ImageLoader from 'image-loader'
Eine weitere bevorzugte Option zur Verwendung von Loadern ist über Ihre Webpack-Konfigurationsdatei. Auf diese Weise können Sie mehr mit Ladeprogrammen tun, z. B. die Dateitypen angeben , auf die Sie die Ladeprogramme anwenden möchten. Dazu erstellen wir ein rules
und spezifizieren die Loader in einem Objekt, die jeweils ein Testfeld mit einem Regex-Ausdruck haben, der mit den Assets übereinstimmt, auf die wir die Loader anwenden möchten.
Wenn beispielsweise der image-loader
im vorherigen Beispiel direkt importiert wurde, können wir ihn in der Webpack-Konfigurationsdatei mit den grundlegendsten Optionen aus der Dokumentation verwenden. Das wird so aussehen:
# webpack.config.js const webpack = require("webpack") const path = require("path") const merge = require("webpack-merge") module.exports = { mode: "development", entry: './src/entry', output: { filename: "webpack-output.js", path: path.resolve(__dirname, "dist"), }, module: { rules: [ { test: /\.(jpe?g|png|gif|svg)$/i, use: [ 'img-loader' ] } ] } }
Sehen Sie sich das test
in dem Objekt, das oben den image-loader
enthält, genauer an. Wir können den Regex-Ausdruck erkennen, der mit allen Bilddateien übereinstimmt: entweder jp(e)g
, png
, gif
oder svg
-Format.
Die letzte Methode zur Verwendung von Loadern ist über die CLI mit dem --module-bind
.
Die Readme-Datei von awesome-webpack enthält eine umfassende Liste von Loadern, die Sie mit webpack verwenden können, die jeweils in Kategorien von Operationen gruppiert sind, die sie ausführen. Unten sind nur einige Lader aufgeführt, die Sie in Ihrer Anwendung nützlich finden könnten:
- Responsive-Loader Sie werden diesen Loader sehr hilfreich finden, wenn Sie Bilder hinzufügen, die zu Ihrer responsiven Website oder App passen. Es erstellt mehrere Bilder verschiedener Größen aus einem einzigen Bild und gibt ein
srcset
zurück, das den Bildern zur Verwendung bei geeigneten Anzeigebildschirmgrößen entspricht. - Babel-Loader
Dies wird zum Transpilieren Ihres JavaScript-Codes von der modernen ECMA-Syntax in ES5 verwendet. - GraphQL-Loader
Wenn Sie ein GraphQL-Enthusiast sind, werden Sie diesen Loader sehr hilfreich finden, da er Ihre.graphql
Dateien lädt, die Ihr GraphQL-Schema, Abfragen und Mutationen enthalten – zusammen mit der Option, die Validierung zu aktivieren.
Plugins
Die Verwendung von Plugins ermöglicht es dem Webpack-Compiler , Aufgaben an Chunks auszuführen, die aus den gebündelten Modulen erstellt wurden. Obwohl Webpack kein Task Runner ist, können wir mit Plugins einige benutzerdefinierte Aktionen ausführen, die die Ladeprogramme nicht ausführen konnten, als der Code gebündelt wurde.
Ein Beispiel für ein Webpack-Plugin ist das in Webpack integrierte ProgressPlugin . Es bietet eine Möglichkeit, den Fortschritt anzupassen, der während der Kompilierung in der Konsole ausgedruckt wird.
# webpack.config.js const webpack = require("webpack") const path = require("path") const merge = require("webpack-merge") const config = { mode: "development", entry: './src/entry', output: { filename: "webpack-output.js", path: path.resolve(__dirname, "dist"), }, module: { rules: [ { test: /\.(jpe?g|png|gif|svg)$/i, use: [ 'img-loader' ] } ] }, plugins: [ new webpack.ProgressPlugin({ handler: (percentage, message ) => { console.info(percentage, message); }, }) ] } module.exports = config
Mit dem Progress-Plugin in der obigen Konfiguration haben wir eine Handler-Funktion bereitgestellt, die während des Kompilierungsprozesses den Kompilierungsprozentsatz und eine Meldung an die Konsole ausgibt.
Unten sind einige Plugins aus der Readme-Datei von awesome-webpack aufgeführt, die Sie in Ihrer Webpack-Anwendung praktisch finden werden.
- Offline-Plugin
Dieses Plugin nutzt zuerst Servicemitarbeiter oder den AppCache, sofern verfügbar, um eine Offline-Erfahrung für Webpack-verwaltete Projekte bereitzustellen. - Purgecss-Webpack-Plugin
Dieses Plugin ist praktisch, wenn Sie versuchen, Ihr Webpack-Projekt zu optimieren, da es während der Kompilierung unbenutztes CSS in Ihrer Anwendung entfernt.
An diesem Punkt haben wir unsere erste Webpack-Konfiguration für eine relativ kleine Anwendung vollständig eingerichtet. Lassen Sie uns weiter überlegen, wie wir bestimmte Dinge mit webpack in unserer Anwendung tun können.
Umgang mit mehreren Umgebungen
In Ihrer Anwendung müssen Sie Webpack möglicherweise entweder für eine Entwicklungs- oder eine Produktionsumgebung anders konfigurieren . Beispielsweise möchten Sie möglicherweise nicht, dass Webpack jedes Mal kleinere Warnprotokolle ausgibt, wenn eine neue Bereitstellung in Ihrer Continuous-Integration-Pipeline in Ihrer Produktionsumgebung vorgenommen wird.
Es gibt mehrere Möglichkeiten, dies zu erreichen, wie von Webpack und der Community empfohlen. Eine Möglichkeit besteht darin , Ihre Konfigurationsdatei zu konvertieren , um eine Funktion zu exportieren, die ein Objekt zurückgibt. Auf diese Weise wird die aktuelle Umgebung vom Webpack-Compiler als erster Parameter und andere Optionen als zweiter Parameter an die Funktion übergeben.
Diese Methode zum Umgang mit Ihrer Webpack-Umgebung ist praktisch, wenn Sie einige Vorgänge basierend auf der aktuellen Umgebung anders ausführen möchten. Bei größeren Anwendungen mit komplexeren Konfigurationen könnten Sie jedoch mit einer Konfiguration enden, die mit vielen bedingten Anweisungen vollgepackt ist.
Das folgende Code-Snippet zeigt ein Beispiel dafür, wie eine production
und eine development
in derselben Datei mithilfe der functions
-Methode behandelt werden.
// webpack.config.js module.exports = function (env, args) { return { mode : env.production ? 'production' : 'development', entry: './src/entry', output: { filename: "webpack-output.js", path: path.resolve(__dirname, "dist"), }, plugins: [ env.development && ( new webpack.ProgressPlugin({ handler: (percentage, message ) => { console.info(percentage, message); }, }) ) ] } }
Wenn Sie die exportierte Funktion im obigen Code-Snippet durchgehen, werden Sie sehen, wie der an die Funktion übergebene env
-Parameter mit einem ternären Operator zum Wechseln von Werten verwendet wird. Es wird zuerst verwendet, um den Webpack-Modus einzustellen, dann wird es auch verwendet, um das ProgressPlugin nur im Entwicklungsmodus zu aktivieren.
Eine weitere elegantere Möglichkeit, mit Ihrer Produktions- und Entwicklungsumgebung umzugehen, besteht darin, unterschiedliche Konfigurationsdateien für die beiden Umgebungen zu erstellen. Sobald wir das getan haben, können wir sie mit verschiedenen Befehlen in den package.json
Skripten verwenden, wenn wir die Anwendung bündeln. Schauen Sie sich den folgenden Ausschnitt an:
{ "name" : "smashing-magazine", "main" : "index.js" "scripts" : { "bundle:dev" : "webpack --config webpack.dev.config.js", "bundle:prod" : "webpack --config webpack.prod.config.js" }, "dependencies" : { "webpack": "^5.24.1" } }
In der Datei „ package.json
oben haben wir zwei Skriptbefehle , die jeweils eine andere Konfigurationsdatei verwenden, die geschrieben wurde, um eine bestimmte Umgebung zu handhaben, wenn die Assets der Anwendung gebündelt werden. Jetzt können Sie Ihre Anwendung mit npm run bundle:dev
im Entwicklungsmodus oder npm run bundle:prod
, wenn Sie ein produktionsreifes Bundle erstellen.
Mit dem zweiten Ansatz vermeiden Sie bedingte Anweisungen , die bei der Rückgabe Ihres Konfigurationsobjekts von einer Funktion eingeführt werden. Allerdings müssen Sie jetzt auch mehrere Konfigurationsdateien pflegen.
Konfigurationsdatei aufteilen
Zu diesem Zeitpunkt umfasst unsere Webpack-Konfigurationsdatei 38 Codezeilen (LOC). Das ist für eine Demo-Anwendung mit einem einzigen Ladeprogramm und einem einzigen Plugin ganz in Ordnung.
Für eine größere Anwendung wird unsere Webpack-Konfigurationsdatei jedoch definitiv viel länger sein und mehrere Loader und Plugins mit jeweils ihren benutzerdefinierten Optionen enthalten. Um die Konfigurationsdatei sauber und lesbar zu halten, können wir die Konfiguration in kleinere Objekte auf mehrere Dateien aufteilen und dann das Paket webpack-merge verwenden, um die Konfigurationsobjekte in einer Basisdatei zusammenzuführen.
Um es auf unser Webpack-Projekt anzuwenden, können wir die einzelne Konfigurationsdatei in drei kleinere Dateien aufteilen: eine für Loader, eine für Plugins und die letzte Datei als Basiskonfigurationsdatei, in der wir die beiden anderen Dateien zusammenfügen.
Erstellen Sie eine webpack.plugin.config.js
-Datei und fügen Sie den folgenden Code ein, um die Plugins mit zusätzlichen Optionen zu verwenden.
// webpack.plugin.config.js const webpack = require('webpack') const plugin = [ new webpack.ProgressPlugin({ handler: (percentage, message ) => { console.info(percentage, message); }, }) ] module.exports = plugin
Oben haben wir ein einzelnes Plugin, das wir aus der Datei webpack.configuration.js
extrahiert haben.
Erstellen Sie als Nächstes eine webpack.loader.config.js
-Datei mit dem folgenden Code für die Webpack-Loader.
// webpack.loader.config.js const loader = { module: { rules: [ { test: /\.(jpe?g|png|gif|svg)$/i, use: [ 'img-loader' ] } ] } }
Im obigen Codeblock haben wir den Webpack-Img img-loader
in eine separate Datei verschoben.
Erstellen Sie schließlich eine webpack.base.config.js
-Datei, in der die grundlegende Eingabe- und Ausgabekonfiguration für die Webpack-Anwendung neben den beiden oben erstellten Dateien gespeichert wird.
// webpack.base.config.js const path = require("path") const merge = require("webpack-merge") const plugins = require('./webpack.plugin.config') const loaders = require('./webpack.loader.config') const config = merge(loaders, plugins, { mode: "development", entry: './src/entry', output: { filename: "webpack-output.js", path: path.resolve(__dirname, "dist"), } }); module.exports = config
Wenn Sie einen Blick auf die obige webpack-Datei werfen, können Sie feststellen, wie kompakt sie im Vergleich zur ursprünglichen webpack.config.js
-Datei ist. Jetzt wurden die drei Hauptteile der Konfiguration in kleinere Dateien aufgeteilt und können einzeln verwendet werden.
Optimierung großer Builds
Wenn Sie über einen längeren Zeitraum an Ihrer Anwendung arbeiten, wird Ihre Anwendung definitiv an Funktionen und Größe zunehmen. Dabei werden neue Dateien erstellt, alte Dateien modifiziert oder umgestaltet und neue externe Pakete installiert – all dies führt zu einer Erhöhung der von Webpack ausgegebenen Bundle-Größe .
Standardmäßig versucht webpack automatisch, Bundles in Ihrem Namen zu optimieren, wenn Ihr Konfigurationsmodus auf production
eingestellt ist. Beispielsweise ist Tree-Shaking eine Technik, die webpack standardmäßig anwendet (beginnend mit webpack 4+), um Ihre Bundle-Größe zu optimieren und zu reduzieren. Im Wesentlichen handelt es sich um eine Optimierungstechnik, mit der nicht verwendeter Code entfernt wird. Auf einer einfachen Ebene werden während des Bündelns die Import- und Exportanweisungen verwendet, um ungenutzte Module zu erkennen, bevor sie aus den ausgegebenen Bündeln entfernt werden.
Sie können Ihr Anwendungspaket auch manuell optimieren, indem Sie Ihrer Konfigurationsdatei ein optimization
mit bestimmten Feldern hinzufügen. Der Optimierungsabschnitt der Webpack-Dokumentation enthält eine vollständige Liste der Felder, die Sie im optimization
verwenden können, um Ihre Anwendung zu optimieren. Betrachten wir eines der 20 dokumentierten Felder.
-
minimize
Dieses boolesche Feld wird verwendet, um Webpack anzuweisen, die Bündelgröße zu minimieren. Standardmäßig versucht Webpack, dies mit TerserPlugin zu erreichen, einem Code-Minifizierungspaket, das mit Webpack geliefert wird.
Bei der Minimierung wird Ihr Code minimiert, indem unnötige Daten aus dem Code entfernt werden, was wiederum die nach dem Prozess erzeugte Codegröße reduziert.
Wir können auch andere bevorzugte Minifier verwenden, indem wir ein minimizer
-Array-Feld innerhalb des optimization
hinzufügen. Ein Beispiel ist die Verwendung von Uglifyjs-webpack-plugin unten.
// webpack.config.js const Uglify = require("uglifyjs-webpack-plugin") module.exports = { optimization { minimize : true, minimizer : [ new Uglify({ cache : true, test: /\.js(\?.*)?$/i, }) ] } }
Oben wird uglifyjs-webpack-plugin
als Minifier mit zwei ziemlich wichtigen Optionen verwendet. Erstens bedeutet die Aktivierung des cache
, dass Uglify vorhandene Dateien nur minimiert, wenn es sich um neue Änderungen handelt, und die test
gibt die spezifischen Dateitypen an, die wir minimieren möchten.
Hinweis: Das uglifyjs-webpack-plugin bietet eine umfassende Liste der verfügbaren Optionen, wenn Sie Ihren Code damit verkleinern.
Eine kleine Optimierungs-Demo
Lassen Sie uns versuchen, eine Demoanwendung manuell zu optimieren, indem wir einige Felder in einem größeren Projekt anwenden, um den Unterschied zu sehen. Obwohl wir nicht tief in die Optimierung der Anwendung eintauchen werden, werden wir den Unterschied in den Bundle-Größen zwischen der Ausführung von Webpack im development
und im production
sehen.
Für diese Demo verwenden wir eine mit Electron erstellte Desktop-Anwendung, die auch React.js für ihre Benutzeroberfläche verwendet – alles zusammen mit dem Webpack. Electron und React.js klingen nach einer ziemlich schweren Kombination und könnten wahrscheinlich ein größeres Bündel erzeugen.
Hinweis : Wenn Sie Electron zum ersten Mal kennenlernen, gibt dieser Artikel einen guten Einblick, was Electron ist und wie Sie es zum Erstellen plattformübergreifender Desktop-Anwendungen verwenden können.
Um die Demo lokal auszuprobieren, klonen Sie die Anwendung aus dem GitHub-Repository und installieren Sie die Abhängigkeiten mit den folgenden Befehlen.
# clone repository git clone https://github.com/vickywane/webpack-react-demo.git # change directory cd demo-electron-react-webpack # install dependencies npm install
Die Desktop-Anwendung ist ziemlich einfach mit einer einzelnen Seite, die mit Stilkomponenten gestaltet ist. Wenn die Desktop-Anwendung mit dem Befehl yarn start
gestartet wird, zeigt die einzelne Seite eine Liste von Bildern an, die von einem CDN abgerufen wurden, wie unten gezeigt.
Lassen Sie uns zunächst ein Entwicklungspaket dieser Anwendung ohne manuelle Optimierung erstellen, um die endgültige Paketgröße zu analysieren.
Durch Ausführen von yarn build:dev
von einem Terminal im Projektverzeichnis wird das Entwicklungspaket erstellt. Außerdem werden die folgenden Statistiken auf Ihrem Terminal gedruckt:
Der Befehl zeigt uns die Statistiken der gesamten Zusammenstellung und der ausgegebenen Bundles.
Beachten Sie, dass der mainRenderer.js
1,11 Mebibyte (ca. 1,16 MB) groß ist. Der mainRenderer
ist der Einstiegspunkt für die Electron-Anwendung.
Als Nächstes fügen wir uglifyjs-webpack-plugin als installiertes Plug-in in der Datei webpack.base.config.js
für die Codeminimierung hinzu.
// webpack.base.config.js const Uglifyjs = require("uglifyjs-webpack-plugin") module.exports = { plugins : [ new Uglifyjs({ cache : true }) ] }
Lassen Sie uns abschließend die Anwendung mit dem Webpack im production
bündeln. Wenn Sie den Befehl „ yarn build:prod
“ von Ihrem Terminal aus ausführen, werden die folgenden Daten an Ihr Terminal ausgegeben.
Notieren Sie sich dieses Mal den mainRenderer
Chunk. Es ist auf satte 182 Kibibyte (ca. 186 KB) gesunken, und das sind mehr als 80 % der zuvor mainRenderer
Chunk-Größe!
Lassen Sie uns die ausgegebenen Bündel mit dem webpack-bundler-analyzer weiter visualisieren. Installieren Sie das Plug-in mit dem Befehl yarn add webpack-bundle-analyzer
“ und ändern Sie die Datei webpack.base.config.js
“ so, dass sie den folgenden Code enthält, der das Plug-in hinzufügt.
// webpack.base.config.js const Uglifyjs = require("uglifyjs-webpack-plugin"); const BundleAnalyzerPlugin = require("webpack-bundle-analyzer"); .BundleAnalyzerPlugin; const config = { plugins: [ new Uglifyjs({ cache : true }), new BundleAnalyzerPlugin(), ] }; module.exports = config;
Führen Sie auf Ihrem Terminal yarn build:prod
aus, damit die Anwendung neu gebündelt werden kann. Standardmäßig startet webpack-bundle-analyzer einen HTTP-Server, der die visualisierte Übersicht der Bundles in Ihrem Browser bereitstellt.
Aus dem obigen Bild können wir eine visuelle Darstellung des ausgegebenen Bündels und der Dateigrößen innerhalb des Bündels sehen. Im Bild können wir beobachten, dass im Ordner node_modules
die größte Datei react-dom.production.min.js
ist, gefolgt von stylis.min.js
.
Anhand der vom Analysator visualisierten Dateigrößen haben wir eine bessere Vorstellung davon, welches installierte Paket den größten Teil des Pakets ausmacht. Wir können dann nach Möglichkeiten suchen, es zu optimieren oder durch ein leichteres Paket zu ersetzen.
Hinweis: Die Webpack-Analyzer-Plug-in- Dokumentation listet andere Mittel auf, die zum Anzeigen der Analyse verfügbar sind, die aus Ihren ausgegebenen Paketen erstellt wurde.
Webpack-Community
Eine der Stärken von Webpack war die große Community von Entwicklern dahinter, und dies war für Entwickler, die Webpack zum ersten Mal ausprobierten, von großem Nutzen. Genau wie dieser Artikel gibt es mehrere Artikel, Leitfäden und Ressourcen mit der Dokumentation, die als großartige Anleitung bei der Verwendung von Webpack dient.
Beispielsweise enthält der Build Performance Guide aus dem Blog von webpack Tipps zur Optimierung Ihrer Webpack-Builds, und die Fallstudie von Slack (obwohl sie etwas alt ist) erklärt, wie Webpack bei Slack optimiert wurde.
Mehrere Community-Ressourcen erklären Teile der Webpack-Dokumentation und stellen Ihnen Beispiel-Demoprojekte zur Verfügung, um zu zeigen, wie Funktionen von Webpack verwendet werden. Ein Beispiel ist ein Artikel über Webpack 5 Module Federation, der erklärt, wie die neue Module Federation-Funktion von Webpack in einer React-Anwendung verwendet wird.
Zusammenfassung
Nach sieben Jahren seines Bestehens hat sich webpack wirklich als wichtiger Bestandteil der JavaScript-Toolchain erwiesen, die von einer Vielzahl von Projekten verwendet wird. Dieser Artikel gibt nur einen Einblick in die Dinge, die man mit der flexiblen und erweiterbaren Natur von webpack erreichen kann.
Wenn Sie das nächste Mal einen Modul-Bundler für Ihre Anwendung auswählen müssen, werden Sie hoffentlich einige Kernkonzepte von Webpack, das Problem, das es löst, und auch die Schritte zum Einrichten Ihrer Konfigurationsdateien besser verstehen.
Weiterführende Literatur zu SmashingMag:
- Webpack - Eine ausführliche Einführung
- Erstellen Sie eine PWA mit Webpack und Workbox
- Einrichten von TypeScript für moderne React-Projekte mit Webpack
- So nutzen Sie die Maschinen: Mit Task Runnern produktiv sein