HTML5-Tutorium: JavaScript: Hello World 05 (Webpack): Unterschied zwischen den Versionen
Kowa (Diskussion | Beiträge) |
Kowa (Diskussion | Beiträge) |
||
Zeile 103: | Zeile 103: | ||
module.exports = | module.exports = | ||
{ entry: | { entry: | ||
{ head: absolutePath(' | { head: absolutePath('src/css/head.css'), | ||
main: absolutePath(' | main: absolutePath('src/js/main.js'), | ||
}, | }, | ||
Version vom 8. April 2021, 10:37 Uhr
Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:
Korrektheit: 3 (zu größeren Teilen überprüft) |
Umfang: 4 (unwichtige Fakten fehlen) |
Quellenangaben: 3 (wichtige Quellen vorhanden) |
Quellenarten: 5 (ausgezeichnet) |
Konformität: 3 (gut) |
Inhalt | Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5 | Teil 6 | Vue 1 | Vue 2 | Vue 3 | Vue 4 | Vue 5 | Vue 6
Musterlösung: index.html
(5a), index.html
(5b), index.html
(5c), index.html
(5d),
(Git-Repositories: 5a, 5b, 5c, 5d)
Anwendungsfälle (Use Cases)
Gegenüber dem dritten Teil des Tutoriums ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.
In diesem Teil des Tutoriums geht es darum, die Anwendung mittels Webpack[1] automatisch für den Server-Betrieb zu optimieren, sodass möglichst wenige, möglichst kleine Dateien zum Client übertragen werden.
Im Tutorium wird „Webpack 5“ verwendet.
Erstellen eines neuen Projektes
Erstellen Sie ein neues Projekt HelloWorld05
als Fork von HelloWorld04
(siehe Hello-World-02-Tutorium).
JavaScript Module Bundlers
Um Module einer Web-Anwendung für die Auslieferung zum Client zu komprimieren, zu bündeln und anderweitig zu optimieren, gibt es zahlreiche Werkzeuge. Für Node.js gibt es die sogenannten “JavaScript Module Bundlers”, wie z. B. Webpack[1], Browserify[2] oder FuesBox[3].
Üblicherweise optimieren die Bundlers nicht nur JavaScript-Dateien, sondern auch HTML-, CSS-, JSON- und andere Dateien.
Webpack ist ein sehr mächtiges Werkzeug, mit dem eine Vielzahl von Web-Dateien in einer oder einigen wenigen JavaScript-Dateien zusammengefasst und bei Bedarf auch komprimiert werden können. Dieser Bundler kommt in vielen Projekten zum Einsatz. Einer der Entwickler von webpack ist Johannes Ewald, ein ehemaliger Student der HSA (vgl. https://github.com/jhnns). Er bietet auch regelmäßig Vorlesung an der HSA zum Thema „JavaScript“ an.
Allerdings hat Webpack auch einige Nachteile:
- Es gibt diverse zugehörige Node.js-Pakete ganz unterschiedlicher Qualität. Für eine Aufgabe das beste oder zumindest ein gutes Paket zu finden, ist häufig eine Sisyphos-Arbeit.
- Mit jedem Versionssprung der Hauptrevisionsnummer haben sich bislang die Schnittstellen und Prinzipien so gravierend geändert, dass man die Webpack-Konfiguration im Wesentlichen neu erstellen musste.
- Auch kann es einem passieren, dass ein Paket, das bislang gewinnbringend verwendet wurde, plötzlich nicht mehr unterstützt wird und aufgrund von neu entdeckten Sicherheitsproblemen auch nicht mehr benutzt werden kann.
Dennoch werden wir im Tutorium Webpack 5 einsetzen. Die Vorteile überwiegen trotz aller Nachteile.
Webpack
Node.js-Pakete
Um Webpack verwenden zu können, müssen Sie zunächst ein Node.js-Projekt anlegen.
npm init -y
Tagen Sie wie im Tutorium HTML5-Tutorium: JavaScript: Entwicklungsumgebung: Node.js beschrieben geeignete Werte in die JSON-Datei package.json
ein (name
, version
, description
,
main
, repository
, keywords
, author
und license
).
Achten Sie darauf, dass Visual Studio Code keine Fehler meldet.
Installieren Sie nun die benötigten Node.js-Pakete:
npm i -D webpack webpack-cli
npm i -D copy-webpack-plugin
npm i -D css-loader style-loader file-loader extract-loader
Das Paket webpack
enthält das eigentlich Webpack-System. webpack-cli
enthält Kommandozeilenbefehle, mit denen Webpack von einer Shell aus oder auch mittels NPM-Skripts gesteuert werden kann.
Das Copy-Webpack-Plugin[4] dient dazu, mittels Webpack Dateien von einem Ordner in einen anderen zu kopieren. Verschiedene Loaders werden verwendet, um CSS- und JavaScript-Dateien für den „Bündelung“ vorzubereiten.[5]
Git commit
Achtung: Bevor Sie einen Commit durchführen, müssen Sie im selben Ordner, in dem sich die Datei package.json
befindet, eine Datei namens .gitignore
anlegen. (Der Punkt zu Beginn des Dateinamens darf nicht fehlen!)
In diese Datei schreiben Sie ein einziges Wort: node_modules
Diese Datei ist extrem wichtig. Wie Sie bereits im Node.js-Tutorium gesehen haben, enthält der
Ordner node_modules
sehr schnell sehr viele Dateien (mehrere Zehntausend).
Wenn Sie diese im Repository speichern, bläht sich dieses extrem stark auf. Die Git-Push- und -Pull-Befehle werden dadurch sehr langsam.
Die Datei .gitignore
dient dazu, dies zu verhindern. In jeder Zeile steht ein Dateiname oder ein Dateipattern (wie zum Beispiel *.log
, das alle Dateien mit der Dateiextension log
beschreibt), um zu verhindern, dass die zugehörigen Dateien ins Git-Repository eingefügt werden.
Wenn Sie dafür sorgen, die Dateien package.json
und package-lock.json
ins Repository eingefügt werden, kann ein anderer Benutzer, der Ihr Git-Repository auf seinen Rechner lädt, die fehlenden Node.js-Module jederzeit ganz einfach restaurieren:
npm i
Fügen Sie nun alle Dateien (mit Ausnahme des Ordners node_modules
ins Repository ein (zum Beispiels mittels git add -u
) und committen Sie die Änderungen.
Webpack
Als nächstes Webpack konfiguriert werden, damit die Dateien web/index.html
, web/css/head.css
und web/js/mains.js
automatisch generiert werden können.
Benennen sie zunächst den Ordner web
ins src
um. Im Ordner src
erstellen Sie künftig neue Dateien, nehmen Änderungen vor etc. Dabei sollten Sie unbedingt darauf, dass sinnvolle Module angelegt werden, viele sinnvolle Kommentare vorhanden sind, die Blöcke mittels Leerzeichen sauber eingerückt sind etc. Verwenden Sie niemals Tab-Zeichen zum Einrücken, da jeder Text-Editor Tab-Zeichen anders einrückt.
Der Inhalt des Ordners web
, der vom Browser dargestellt wird, soll künftig mittels Webpack generiert werden. Erstellen Sie dazu im Wurzelverzeichnis des Projektes die Datei webpack.config.js
(die Sie unbedingt auch in Git speichern sollten). Fügen Sie folgenden Code in diese Datei ein.
webpack.config.js
const
path = require('path'),
CopyPlugin = require('copy-webpack-plugin');
function absolutePath(l_path)
{ return path.resolve(__dirname, l_path); }
module.exports =
{ entry:
{ head: absolutePath('src/css/head.css'),
main: absolutePath('src/js/main.js'),
},
output:
{ filename: 'js/[name].js',
path: absolutePath('web'),
},
plugins:
[ new CopyPlugin
({ patterns:
[{ context: 'src',
from: '*.html',
to: '.',
},
],
}),
],
module:
{ rules:
[ { test: /head\.css$/,
include: [ /src/ ],
use: [ { loader: 'file-loader',
options: { name: '[name].[ext]',
outputPath: 'css/'
}
},
'extract-loader',
'css-loader'
]
},
{ test: /\.css$/,
include: [ /src/ ],
exclude: [ /head\.css$/ ],
use: [ 'style-loader',
'css-loader'
]
},
]
},
};
Es handelt sich um ein JavaScript-Datei, die direkt von Node.js interpretiert wird.
Aus diesem Grund wird auch nicht das EcmaScript-6-Modul-Konzept eingesetzt, sondern
CommonJS, das Standard-Modulkonzept vom Node. Hier werden Module mittels require
und nicht mittels import
importiert. Für Sie ist das allerdings nebensächlich,
da Sie im Rahmen der Tutorien keine eigenen komplexen Konfigurationsdateien für webpack implementieren werden.
Im Prinzip macht diese Datei nichts anderes als ein Objekt zu exportieren, das Webpack-Konfigurationsinformationen enthält:
entry
: JavaScript-Dateien, die gebündelt und komprimiert werden sollen. Man muss jeweils nur die Wurzeldatei angeben. webpack sucht in dieser Datei rekursiv nach Import-Befehlen und packt die benötigten Dateien ebenfalls in die Ausgabedatei.output
: Hier wird festgelegt, wie die gepackten Dateien heißen sollen. Für jeden Eintrag im Attributeentry
wird eine Datei mit dem Namenweb/js/[name].js
erzeugt, wobei[name]
durch den Schlüsselname des Entry-Eintrags ersetzt wird. In der obigen Datei gibt es zwei Entry-Elemente.plugins
: Hier werden Webpack-Hilfsmodule geladen, die bestimmte Zusatzaufgaben erledigen. Sie verwenden derzeit nur das ModulCopyPlugin
. Dieses kopiert alle HTML-Dateien (das ist in Ihrem Fall nur die Dateiindex.html
) vom Ordnersrc
in den Ausgabe-Ordnerweb
. (In einer späteren Webpack-Konfiguration wird auch noch die HTML-Datei komprimiert werden.)module
: In diesem Attribut werden Regeln (rules
) angegeben,die festlegen, auf welche Weise eine Datei transformiert werden sollen. Bei jeder Regel gibt es einen Test, der festlegt, für welche Dateien die jeweilige Regel zutrifft. Mit Hilfe eines regulären Ausdrucks wird im Tutoriumsbeispiel geprüft, ob die aktuelle Datei aufhead.css
oder.css
endet, sich aber vonhead.css
unterscheidet. Je nach Dateiname werden andere Loader zum Laden und Verarbeiten der zugehörigen Datei verwendet. (Für webpack gibt es diverse Loader, einige davon haben Sie zuvor mit Hilfe vonnpm
installiert.) Leider gibt es soviel Loader, dass die Auswahl geeigneter Loader nicht gerade einfach ist. Erschwerend kommt hinzu, dass sich mit jeder neuen Hauptversion von webpack nicht nur die Struktur der Konfigurationsdatei, sonder auch die verfügbaren Loader und Plugins verändern. :-( )
CSS-Dateien werden zunächst mit dem CSS-Loader geladen und verarbeitet. Anschließend wird die Datei
head.css
vom File-Loader Anweisungen in die Datei web/css/head.css
geschrieben.
Dies hätten wir auch mit dem Copy-Plugin erreicht. Allerdings kann man für den File-Loader einen Optimierer hinzufügen, der die CSS-Datei komprimiert (minimiert), bevor sie in den Web-Ordner eingefügt wird (siehe Version 5b).
Alle übrigen CSS-Dateien werden nicht auf die Platte geschrieben, sondern in die JavaScript-Datei eingefügt, die die CSS-Datei importiert. Dies ist die Aufgabe des Style-Loaders. JavaScript-Dateien werden von Webpack automatisch zu einer Datei zusammengefasst und (im Produktionsmodus) minimiert. Dies ist das Defaultverhalten des JavaScript-Bundlers und braucht daher nicht in eigenen Regeln beschrieben zu werden.
Mit dem Style-Loader wird erreicht, dass die Datei src/css/main.css
in der
Ausgabedatei web/js/main.js
enthalten ist. Damit wird die Zahl der Dateien reduziert: Aus src/js/main.js
, src/js/greet.js
und src/css/main.css
erzeugt Webpack eine (minimierte)
Datei namens web/js/main.js
Damit steht einer Verwendung von Webpack nichts mehr im Wege. Man könnte Webpack nun direkt von der Kommandozeile aufrufen. Besser ist es allerdings NPM-Skript-Befehle zu verwenden.
NPM-Skripte
Fügen Sie in das scripts
-Objekt der Datei package.json
folgende Skript-Anweisungen ein:
"scripts": {
"predev": "rm -rf web/*",
"dev": "webpack --mode development",
"preprod": "rm -rf web/*",
"prod": "webpack --mode production",
"postprod": "rm web/js/head.js",
"prewatch": "rm -rf web/*",
"watch": "webpack --mode development --watch"
}
Dieser Konfiguration definiert drei NPM-Skripte: dev
, prod
und watch
.
Diese Skript können Sie von der Kommandozeile aus starten:
npm run dev
npm run prod
npm run watch
Die Skripte predev
, preprod
und prewatch
werden jeweils ausgeführt, bevor die eigentlichen Skripte ausgeführt werden. In allen drei Fällen wird der Web-Ordner vollständig gelöscht, da er ja neu erstellt werden soll. Für das NPM-Skript prod
gibt es auch noch das Skript postprod
, das
nach dem Skript prod
ausgeführt wird. Es löscht die Datei web/js/head.js
, die von Webpack angelegt wurde. Sie wird allerdings nicht mehr gebraucht, da mit daraus mit dem File-Loader die Datei
web/css/head.css
extrahiert wurde, die von der Datei web/index.html
direkt eingelesen wird.
Geben Sie nun im Terminal die Anweisung npm run dev
(dev = development) ein.
Wenn Sie alles richtig gemacht haben, müsste Webpack fehlerfrei durchlaufen und die Dateien
web/index.html
, web/js/main.js
sowie web/css/head.css
(sowie die überflüssige Datei web/js/head.js
) erstellen. Im Zweifelsfall müssen Sie auf das Reload-Icon hinter HELLOWRLD05A
klicken.
Wenn Sie jetzt die Datei index.html
im Browser öffnen, sollten Sie nach kurzer Zeit
wieder das Begrüßungsmenü sehen. Nach Eingabe des Namens und Klick auf den Say-hello-Button
oder Drücken der Enter-Taste sollten Sie freundlich begrüßt werden.
Allerdings ist das CSS-Layout immer noch mangelhaft. Die Datei main.css
wird bislang noch nicht eingebunden. Das können Sie ganz einfach ändern.
Fügen Sie in die Datei src/js/main.js
folgenden Import-Befehl am Anfang der Datei ein:
import '../css/main.css';
Dieser Befehl ist in JavaScript eigentlich nicht erlaubt. Wenn Sie jetzt versuchen, die Datei
src/index.html
im Browser zu öffnen, werden Sie in der Browser-Konsole
eine Fehlermeldung erhalten.
Webpack unterstützt allerdings das Importieren von CSS-Dateien in JavaScript-Dateien. Das Tool wurde so konfiguriert, dass die CSS-Datei dynamisch in das HTML-Dokument „injiziert“ wird (siehe oben).
Geben Sie im Terminal noch einmal die Anweisung npm run dev
ein
und öffnen Sie die Datei web/index.html
im Browser (nicht die Datei src/index.html
!). Jetzt sollte sie wieder sauber formatiert sein
(evtl. erst nach einem Reload im Browser)!
Sehen Sie sich mal den Inhalt der Datei main.js
an. Darin finden Sie
– neben vielen Kommentaren, die zur Strukturierung der Datei verwendet werden – die Inhalte der Dateien main.js
, greet.js
und main.css
sowie spezielle Anweisungen, die von Webpack eingefügt wurden.
In dieser Form ist die Datei für Entwicklungszwecke einigermaßen brauchbar. Bei einem Fehler zeigt einem der Browser, in welcher Zeile dieser Datei der Fehler aufgetreten ist. Normalerweise handelt es sich um eine Zeile, die Sie erfasst haben. Webpack-Befehle sollten keine Fehler werfen. Nachteilig ist, dass diese Zeile etwas anders aussehen kann, wie in Ihrem Sourcecode, da sie eventuell transformiert wurde. Aber man findet die Originalzeile normalerweise recht schnell.
Gehen Sie nochmal ins Terminal und geben Sie diesmal
die Anweisung npm run prod
(prod = production) ein.
Es werden wieder die drei Dateien erstellt. Und die Web-Anwendung sollte
immer noch funktionieren. Wenn Sie sich die gebündelte JavaScript-Datei web/js/main.js
noch einmal ansehen,
werden Sie feststellen, dass sie nun viel kleiner ist. Sie enthält keine überflüssige Leerzeichen, keine Zeilenumbrüche
und auch keine Kommentare mehr (evtl. mit Ausnahme des Kommentars, der Auskunft über den Autor der CSS-Datei main.css
). Diese Datei ist für den Produktivbetrieb viel besser geeignet, da sie weniger Bandbreite
verbraucht. Insbesondere Smartphone-Besitzer freuen sich über kleine Dateien, da ihr Datenvolumen
dadurch weniger belastet wird. Für die Fehlersuche bei der Entwicklung der Web-App ist diese
Variante allerdings vollkommen ungeeignet.
Nun können Sie noch die Anweisung npm run watch
testen.
Dieser startet einen Webpack-Watcher, der bei jeder Änderung an einer Datei, die von webpack
beim Bündeln berücksichtigt wird, dafür sorgt, dass die Dateien im Web-Ordner neu erstellt werden
und Sie die Ergebnisse Ihrer Änderung durch einen einfachen (Auto-)Reload der Datei index.html
im Browser betrachten können. Ändern Sie doch einmal in der CSS-Datei src/css/head.css
(nicht in der Datei web/css/head.css
) die Hintergrundfarbe, speichern Sie die Datei und
laden Sie danach die HTML-Datei im Browser mittels des Reload-Buttons neu.
Fortsetzung des Tutoriums
Sie sollten nun Teil 6 des Tutoriums bearbeiten. In diesem Teil des Tutoriums wird ausgenutzt, dass in die Konfigurationsdatei von Webpack ein SCSS-Loader integriert wurde. Damit kann man das Prinzip “Don't Repeat Yourself” (DRY) auch für CSS-Dateien umsetzen.
Quellen
- Kowarschick (MMProg): Wolfgang Kowarschick; Vorlesung „Multimedia-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2018; Quellengüte: 3 (Vorlesung)