HTML5-Tutorium: JavaScript: Hello World 04
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
,
(SVN-Repository)
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 besser zu strukturieren, d. h. zu modularisieren.
Modularisierung
Eine Anwendung, wie z. B. ein HTML5-Spiel, besteht aus diversen unterschiedlichen Komponenten mit ganz unterschiedlichen Aufgaben. Bei einem HTML5-Spiel müssen die Spielfiguren, die Spielszenen, die Spiellogik, die Benutzereingaben, die Darstellung das Spiels im Browser etc. erstellt und verwaltet werden, wobei das Erstellen und Verwalten teilweise während der Spiel-Entwicklung und teilweise während der Spiel-Ausführung (Runtime) erfolgt. An der Entwicklung eines Spiels sind üblicherweise mehrere oder gar viele Entwickler gleichzeitig beteiligt. Oft müssen einzelnen Komponenten an neue Endgeräte oder Betriebssysteme angepasst werden. Beispielsweise muss eine Tastatursteuerung durch eine Touch- oder Gestensteuerung ersetzt werden, wenn ein Spiel so erweitert werden soll, dass es auch auf einem Smartphone oder Tablet läuft.
Das alles ist nur machbar, wenn man die Anwendung modularisiert, d. h. in kleine, möglichst unabhängige Komponenten unterteilt. Ein großer Feind der Modularisierung sind globale Variablen und Funktionen. Je mehr Dateien von unterschiedlichen Autoren erstellt werden, desto größer ist die Gefahr, dass es zu Namenskollisionen kommt. Daher gilt der Grundsatz: Verwende so wenig globale Größen wie möglich.
Erstellen eines neuen Projektes
Achtung: Es ist extrem wichtig, dass Sie folgende Befehle in der richtigen Reihenfolge durchführen.
Wenn Sie den zweiten und den dritten der der nachfolgenden Befehlsliste vertauschen, fügt WebStorm
den Ordner node_modules
in Subversion ein und deaktiviert die Möglichkeit, ihn zur SVN-Ignore-Liste hinzufügen. Dann müssen Sie den Ordner wieder löschen und noch einmal hinzufügen. Später kann es sogar sein, dass ein nachträgliches Hinzufugen zur Ignore-Liste gar nicht mehr möglich ist. Dann müssten Sie dies mit einem anderen Tool (wie TortoiseSVN) nachholen.
Also: Arbeiten Sie die Befehle in der vorgegebenen Reihenfolge ab.
- Erstellen Sie ein neues Projekt mit dem Namen „
HelloWorld04
“ - Speichern Sie das Projekt in Ihrem Repository.
- Erstellen Sie den Ordner
node_modules
im Wurzelverzeichnis. - * Die Frage „Do you want to scedule the following directory for addition to Subversion?“ beantworten Sie mit „
No
“. - Rechtsklick auf
node_modules
→Subversion
→Ignore
→ Klick aufnode_modules
- Klick auf das Commit-Icon.
Dadurch, dass Sie das Verzeichnis node_modules
zur SVN-Ignore-Liste hinzugefügt haben,
werden die Datein, die in Zukunft in diesem Ordner gespeichert werden, nicht ins SVN-Repository übertragen. Dies ist notwendig, da sich in diesem Ordner mehrere tausend ganz kleine Dateien befinden
werden, und die Speicherung dieser Daten im SVN-Repository Stunden in Anspruch nehmen kann.
Dabei ist eine Speicherung gar nicht notwendig, da sie jederzeit mit dem Befehl npm install
sehr schnell wieder hergestellt werden können.
BTW: Sollten Sie einmal eine Abschlussarbeit mit Node.js erstellen, fügen Sie bitte auf gar keinen Fall den Inhalt des Ordners node_modules
in Ihr Abgabemedium (CD, DVD, USB-Stick ...) ein.
Erstellen einer Ordnerstruktur
Grundsätzlich gilt auch bei der Programmierung: Ordnung ist das halbe Leben.
Web-Anwendungen werden sehr schnell sehr groß. Also sollte man sich eine geeignete Ordnerstruktur überlegen.
Üblicherweise legt man CSS-Dateien in einen Ordner namens „css
“ und JavaScript-Dateien in einen Ordner namens
„js
“ oder „lib
“. Sollten es viele CSS- und/oder JavaScript-Dateien werden,
legt man im entsprechenden Ordner geeignete Unterordner an.
Legen Sie im Root-Verzeichnis Ihres Projektes folgende Ordner an (und beantworten Sie die Frage, ob der Ordner im SVN-Repository gepichert werden soll, jeweils mit Yes
):
web
: Der Inhalt dieses Ordners kommt später auf einen echten Web-Server.src
: Der Inhalt dieses Ordners enthält die Ausgangsdateien, die mit Hilfe von Node.js noch transformiert und dann in den Web-Ordner kopiert werden.web/css
: Hier wird in den Vorlesungstutorien jeweils nur eine sehr kleine Datei liegen: „initial.css
“. Diese sorgt dafür, dass das Fenster der App während der Initialisierung kein defektes LAyout präsentiert. Der größte Teil des CSS-Codes wird später dynamisch (per JavaScript) geladen.web/js
: Hierher kopiert Node.js die erzeugten JavaScript-Dateien.src/css
: Hier werden die eigentlichn CSS-Dateien der Web-Anwendung gespeichert, die von der App dynamisch nachgeladen werden sollen. In diesem Ordner könnten zur weiteren Strukturierung Unterordner angelegt werden. Allerdings wird das in dieser Veranstaltung nicht notwendig sein. Es wird jeweils nur eine Datei namens „main.css
“ oder „main.scss
“ geben.src/js
: Hierher kommt die Datei „app.js
“, die für den Start der Web-Anwendung zuständig ist. Üblicherweise liest sie weitere JavaScript-Dateien sowie eine oder mehrere JSON-Dateien mit Initialwerten ein, initialisiert die Anwendung und startet sie da nn.src/js/app
: Hier speichern Sie die übrigen von Ihnen geschriebenen JavaScript-Dateien Ihrer Web-Anwendung. In diesem Ordner werden i. Allg. Unterordner zur weiteren Strukturierung der Anwendung angelegt.
Fremde Bibliotheken und automatisch generierte JavaScript-Dateien enthalten häufig unsauberen Code, die Ihnen von WebStorm beim Speichern der Dateien im Repository angezeigt werden. In einer Rückfrage sollen Sie dann bestätigen, dass Sie die „fehlerhaften“ Dateien trotzdem speichern wollen.
Damit Ihnen bei einem Commit nur Fehler in Ihren eigenen Dateien angezeigt werden, schließen Sie die Ordner „mode_modules
“ und „web/js
“ von der
WebStorm-Fehlerüberwachung aus:
- Rechtklick auf den Ordner „
mode_modules
“ →Mark Directory as
→Excluded
- Rechtklick auf den Ordner „
web/js
“ →Mark Directory as
→Excluded
Kopieren Sie nun aus Ihrer Lösung des dritten Teil des Tutoriums die Dateien „index.html
“ und „main.css
“ in den soeben erstellten Ordnerbaum und speichern Sie diese unter den Namen „web/index.html
“ und „src/css/main.css
“
Noch ein kleiner Tipp: Aktivieren Sie die WebStorm-Node.js-coding-assitence, da Sie anderenfalls bei jedem SVN-Commit einen Fehler angezeigt bekommen:
File
/WebStorm
→ Settings
/Preferences
→ Language & Frameworks
→ Node.js and NPM
→ Node.js Core library is not enabled. Enable
Damit Sie dies nicht bei jedem Projekt wiederholen müssen, konfigurieren Sie auch Ihre Default Settings/Default Preferences entsprechend.
File
/WebStorm
→ Default Settings
/Default Preferences
→ Language & Frameworks
→ Node.js and NPM
→ Node.js Core library is not enabled. Enable
Sie sollten nach jeden größeren Entwicklungsschritt die Änderungen im Repository speichern:
- Klick auf das SVN-Commit-Icon.
Die App
Laden der CSS- und der JavaScript-Dateien
Eine Web-Anwendung funktioniert nur – wie Sie bereits erfahren haben –, wenn nicht nur die HTML-Datei, sondern auch die zugehörigen CSS- und JavaScript-Dateien geladen werden. Allerdings gibt es dabei ein Problem: Die CSS- und JavaScript-Dateien werden im Laufe der Zeit immer zahlreicher und/oder größer. Diese Dateien zu laden, dauert seine Zeit.
In der aktuellen fritten Version der Web-Anwendung stehen die Verweise auf diese Dateien im head
-Bereich des Dokuments.
Dieser wird vollständig geladen, bevor der body
-Bereich eingelesen wird. Das heißt aber, dass der Browser keine Inhalte des HTML-Dokuments
darstellen kann, solange er die JavaScript- und CSS-Dateien lädt. Wenn dies zu lange dauert, verliert der Besucher die Geduld und verlässt die Seite
vorzeitig.
Besser wäre es daher andersherum vorzugehen: Es wird zuerst der body
-Bereich geladen und dann die JavaScript- und die CSS-Dateien.
Im Falle von JavaScript ist das durchaus sinnvoll, aber im Falle von CSS hat das den Effekt, dass der Browser noch keine Layout-Vorgaben erhalten hat,
wenn er mit dem Rendern der Seite beginnt. Also verwendet er die browserspezifischen Defaultwerte. Das heißt, die Seite sieht zunächst
ganz anders aus, als vom Designer geplant. Wenn dann die CSS-Dateien geladen wurden, wird die Seite erneut gerendert und verändert ihr Aussehen.
Auch das ist verwirrend und wirkt unprofessionell.
Was also machen?
CSS-Dateien
Für CSS-Dateien empfiehlt Google ernsthaft, das Link-Element ganz ans Ende der HTML-Datei zu stellen, also nach dem schließenden html
-Tag. Damit das Problem mit dem falschen Layout nicht auftritt, sollen ganz wenige, wichtige CSS-Befehle direkt – d. h. als CSS-Befehle innerhalb eines style
-Elements – in dem HTML-Head-Bereich eingefügt
werden.[1]
Von ersten Vorschlag rate ich dringend ab, da er nicht HTML-konform ist, ja noch nicht einmal SGML-konform. Der zweite Vorschlag hat zur Folge, dass Struktur (HTML) und Layout (CSS) vermischt werden. Dies war einer der Kardinalfehler von frühen HTML-Versionen aus der Zeit, bevor es das CSS-Format gab. Tun Sie das i. Allg. nicht. Aber: Sie können webpack[2] dazu bringen, dies dynamisch zur Laufzeit für Sie nachzuholen.
Gehen Sie so vor, wie es unter Multimedia-Programmierung: Best Practices beschrieben ist. In diesem und den folgenden Tutorien werden diese Prinzipien berücksichtigt.
Legen Sie die Datei web/css/initial.css
an und fügen Sie folgenden (sehr kurzen!) Code ein:
body { background-color: #C5EFFC; }
.hidden { display: none; }
In der Datei src/css/main.css
können Sie das .hidden
-Element entfernen.
In der Datei web/index.html
müssen Sie das Link-Element in Header folgendermaßen
<link rel = "stylesheet" type = "text/css" href = "css/initial.css"/>
anpassen. Das heißt, Sie laden im HTML-Head-Bereich nur noch die kleine CSS-Datei.
JavaScript-Dateien
Für JavaScript-Dateien empfiehlt Google ebenfalls, diese nicht schon zu Beginn zu laden.[3] Dieser Vorschlag ist sehr sinnvoll.
Entfernen Sie das script
-Element aus dem HTML-Header-Bereich und fügen vor dem schließenden body
-Tag folgendes Script-Element ein:
<body>
...
<script type="text/javascript" src="js/app.bundle.js"></script>
</body>
Fügen Sie außerdem in das erste section
-Tag im Body das Attribut
class="hidden"
ein, damit man auch dieses Element beim Laden der Anwendung
zunächst nicht sieht. In einer Anwendung, die zum Laden etwas länger dauert, würde man
einen so genannten Splash Screen sichtbar einfügen und diesen beim eigentlichen Start der App ausblenden.
Wenn Sie nun die Web-App testweise starten, sollten Sie eine himmelblaue, aber ansonsten leere Seite sehen.
Wenn Sie im Browser die Konsole öffnen, sehen Sie dort (evtl. nach einem Reload), eine Fehlermeldung,
dass die JavaScript-Datei app.bundle.js
nicht gefunden wird. Dieser Fehler ist nicht
weiter erstaunlich, da es diese Datei ja noch gar nicht gibt.
Weiter unten im Tutorium wird beschrieben, wie Sie mit Hilfe eines ES6-Import-Befehls und webpack dafür sorgen,
dass diese Datei nicht nur den JavaScript-Code der Anwendung bereit stellt, sondern auch den Inhalt
der eigentlichen CSS-Datei main.css
dynamisch in die HTML-Datei einfügt (injiziert).
Vergessen Sie nicht:
- Klick auf das SVN-Commit-Icon.
Modularisierung der JavaScript-Dateien
Die JavaScript-Datei main.js
aus dem dritten des Tutoriums wird in zwei Teile aufgespalten:
greet.js
und app.js
. Die erste Datei enthält die eigentliche Begrüßungsfunktionalität,
die zweite initialisiert die App, d. h. aktiviert die Begrüßungsfunktion.
Erstellen Sie folgende zwei JavaScript-Dateien:
src/js/greet.js
/**
* @namespace greet
* Contains methods to say hello to the user of the web app.
*/
/**
* Welcomes the user of the web app by displaying a welcome message
* that includes his name. The name is fetched from a text input field.
*/
export const sayHello =
function()
{
document.getElementById('heading_hello').innerHTML =
'Hello, ' + document.getElementById('input_name').value + '!';
document.getElementById('section_form').classList.add('hidden');
document.getElementById('section_hello').classList.remove('hidden');
};
/**
* A keyboard event observer. It tests whether the enter key has been pressed.
* If so, the greet method is activated. Default reactions of the browser are
* disabled.
* @param {KeyboardEvent} p_event - A standard JavaScript keyboard event object
* (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
*/
export const sayHelloOnEnter =
function(p_event)
{
if ( (p_event.code === 'Enter' || p_event.keyCode === 13) &&
document.activeElement === document.getElementById('input_name')
)
{
p_event.preventDefault();
p_event.stopPropagation();
sayHello();
}
};
Sie sehen, dass dieses Modul zwei Funktionen exportiert. Diese (und nur diese) können jetzt von anderen Modulen importiert und damit genutzt werden. Dies nutzen Sie im zweiten Modul aus:
src/app.js
import '../css/main.css';
import * as greet from './app/greet.js';
// Initialize the app.
document.getElementById('button_submit')
.addEventListener('click', greet.sayHello);
window .addEventListener('keydown', greet.sayHelloOnEnter);
// As now all files have been loaded and all data has been
// initialized, the app is ready to start.
// So make the form visible!
document.getElementById('section_form').classList.remove('hidden');
Sie importieren alle Elemente (*
), die Ihnen das Modul src/app/greet.js
zur Verfügung stellt, und speichern diese Elemente in einem Objekt namens greet
.
Damit ist es Ihnen mäglich die beiden Funktionen sayHello
und sayHelloOnEnter
zu verwenden. Sie können jeweils unter dem Namen greet.sayHello
bzw. greet.sayHelloOnEnter
,
auf sie zugreifen.
Weil Sie schon gerade dabei sind, importieren Sie am besten gleich auch noch
die CSS-Datei main.css
. Webpack sorgt dann dafür, dass diese
Datei in die Datei app.bundle.js
integriert wird und somit dynamisch
geladen wird, sobald der Browser die Script-Anweisung
<script type="text/javascript" src="js/app.bundle.js"></script>
ausführt.
Der letzte Befehl in der JavaScript-Datei app.js
document.getElementById('section_form').classList.remove('hidden');
sorgt dafür, dass das Eingabeformular sichtbar wird. Da die notwendigen Callback-Funktionen zuvor mit dem Formular verknüpft wurden, ist es jetzt einsatzbereit, und es spricht nichts mehr dafür, den Benutzer länger an der Verwendung dieses genialen ( :-) ) Formulars zu hindern.
Vergessen Sie nicht:
- Klick auf das SVN-Commit-Icon.
Node.js, Grunt, Babel und webpack
Eigentlich wäre Sie jetzt fertig, wenn denn die Standardbrwoser die ES6-Import- und Export-Befehle kennen würden. Doch das ist leider in den allermeisten Fällen nicht der Fall. Daher müssen die ES6-Dateien in ES5-Dateien transformiert werden. Dafür gibt es diverse Möglichkeiten. Ich empfehle derzeit „webpack“[4].
Zum Transformieren und Packen von JavaScript-, JSON- und CSS/SCSS-Dateien kommen neben webpack auch noch Grunt[5] und Babel[6] zum Einsatz. Diese Pakete kennen Sie ja schon aus dem Tutorium „Einrichten eine Entwicklungsumgebung für Web-Anwendungen“.
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. Es handelt sich also um einen JavaScript module bundler. 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.
Node.js-Pakete
Öffnen Sie das WebStorm-Terminal und installieren Sie die benötigten Node.js-Pakete
npm init -y
# Autor, Lizenz und Keywords in package.json anpassen
npm install --save-dev grunt grunt-contrib-watch
npm install --save-dev babel-cli babel-preset-env
npm install --save-dev webpack grunt-webpack
npm install --save-dev babel-loader json-loader style-loader css-loader
Achtung: grunt-cil
wird auch benötigt. Aber dieses Paket wurde schon
im Tutorium „Einrichten eine Entwicklungsumgebung für Web-Anwendungen“
global installiert und braucht daher nicht noch einmal installiert zu werden.
Sorgen Sie nun dafür. dass die Dateien package.json
und package-lock.json
auch im Repository gespeichert werden (Leider erledigt die WebStorm nicht automatisch):
- Rechtklick auf „
package.json
“ →Subversion
→Add to VCS
- Rechtklick auf „
package-lock.json
“ →Subversion
→Add to VCS
webpack
Nun müssen noch webpack und Grunt konfiguriert werden, damit die Datei app.bundle.js
automatisch generiert werden kann.
Erstellen Sie im Wurzelverzeichnis des Projektes folgende Datei:
webpack.config.js
const path = require('path');
function absolutePath(l_path)
{ return path.resolve(__dirname, l_path);
}
module.exports =
{ entry:
{ app: absolutePath('src/js/app.js')
},
output:
{ filename: '[name].bundle.js',
path: absolutePath('web/js')
},
module:
{ rules:
[ { test: /\.json$/,
loader: 'json-loader'
},
{ test: /\.js$/,
use: [ { loader: 'babel-loader',
options:
{ presets: ['env'],
ignore: '/node_modules/'
},
},
],
},
{ test: /\.css$/,
use: [ 'style-loader',
{ loader: 'css-loader', options: { minimize: true } }
]
}
],
},
plugins:
[],
};
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,
das Sie im Rahmen der Tutorien keine komplexen Konfigurations-Dateien für webpack implementieren werden.
Im Prinzip macht diese Datei nichts andere als ein Objekt zu exportieren, das webpack-Konfigurations-Informationen 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 festgelgt, wie die gepackten Dateien heißen sollen. Für jeden
Eintrag im Attribute entry
wird eine Datei mit dem Namen <[name].bundle.js
erzeugt, wobei [name]
durch den Schlüsselname des Entry-Eintrags ersetzt wird.
In der obigen Datei gibt es nur ein Entry-Element. Dessen Schlüsselname lautet app
.
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 jeweilge Regel zutrifft. Mit Hilfe eines
regulärer Ausdrücke wird im Tutoriumsbeispiel geprüft, ob die aktuelle
Datei auf .json
, .js
oder .css
endet. Je nach der
Endung wird ein anderer Loader zum Laden und Verarbeiten der Datei verwendet.
(Für webpack gibt es diverse Loader, einige davon haben Sie zuvor mit Hilfe von npm
installiert.)
JSON-Dateien werden mit dem JSON-Loader geladen und in die Ergebnis-Datei (app.bundle.js
)
eingefügt.
JavaScript-Dateien werden mit dem Babel-Loader geladen und transformiert.
Auf welche Weise der Babel-Loader dies macht wird nicht mehr in der Datei .babelrc
festgelegt, sondern direkt in der Datei webpack.config.js
. Der Loader kann
auch Dateien laden, die sich im Verzeichnis node_modules
befinden.
Die dort gespeicherten Module sorgen allerdings selbst dafür, dass sie ausführbaren
Web-Code bereitstellen. Daher sollten sie vom Babel-Loader nicht noch einmal transformiert werden.
Mit ignore: '/node_modules/'
wird also nicht festgelegt, dass Babel die
benötigten Dateien nicht lädt, sondern es wird festgelegt, dass sie nicht noch einmal transformiert werden.
CSS-Dateien werden zunächst mit dem CSS-Loader geladen und verarbeitet. Anschließend werden vom
Style-Loader Anweisungen in die Datei app.bundle.js
geschrieben, die dafür sorgen,
dass die CSS-Elemente beim Laden dieser JavaScript-Datei direkt in den HTML-Head-Bereich
der zugehörigen HTML-Datei eingefügt (injiziert) werden.
Am Ende der Konfigurations-Datei, gibt es noch eine Plugin-Liste, die dazu genutzt werden kann,
dateiunabhängige Transformationen an der Ergebnis-Datei (app.bundle.js
)
vorzunehmen. Derartige Plugins werden zunächst einmal nicht verwendet.
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 oder gar Grunt-Befehle zu verwenden.
NPM-Skripte
Fügen Sie das scripts>
-Objekt der Datei package.json
drei weitere Skript-Anweisungen ein:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"bundle": "webpack",
"compress": "webpack -p",
"watch": "webpack --watch"
},
Geben Sie nun im WebStorm-Terminal die Anweisung npm run bundle
ein.
Wenn Sie alles richtig gemacht haben, müsste webpack fehlerfrei durchlaufen und die Datei web/js/app.bundle.js
erstellt werden. Im Zweifelsfall müssen Sie auf das Reload-Icon unter der
Menü-Leiste klicken, um sie zu sehen.
Wenn der Dateiname nicht grün, sondern braun eingefärbt ist, müssen Sie sie unter SVN-Kontrolle stellen:
- Rechtklick auf „
app.bundle.js
“ →Subversion
→Add to VCS
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.
Sehen Sie sich mal den Inhalt der Datei app.bundle.js
an. Darin finden Sie
– neben vielen Kommentaren, die zur Strukturierung der Datei verwendet werden – die Inhalte der Dateien greet.js
, app.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 Brwoser, 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 werden. NAchteilig ist, dass diese Zeile etwas anders ausseen kann, wie in IHrem Sourcecode, das sie ja mittels Babel transformiert wurde. Aber man findet die ORiginalzeile normalerweise recht schnell.
Gehen Sie nochmal ins WebStorm-Terminal und geben Sie diesmal
die Anweisung npm run compress
ein.
Es wird wirder die Datei app.bundle.js
erstellt. Und die Web-Anwendung sollte
immer noch funktionieren. Wenn Sie sich die gebündelte JavaScript noch einmal ansehen,
stellen Sie fest, dass Sie nun viel kleiner ist. Sie enthält keine überflüssige Leerzeichen, keine Zeilenumbrüche
und auch keine Kommentare mehr (mit Ausnahme des Kommentars, der Auzskunft über den Autor und die
Lizenz gibt). Diese Datei ist für den Produktivbetrieb viel besser geeignet, da sie weniger Bandbreite
verbraucht. Insbesondere Smarphone-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 app.bundle.js
neu erstellt wird
und Sie die Ergebnisse Ihrer Änderung durch einen einfachen Reload der Datei index.html
im Browser betrachten können. Änderin Sie doch einmal in der CSS-Datei die Hintergrundfarbe, speicher Sie die Datei un beobachten Sie das Terminalfenster. Laden Sie danach die HTML-Datei im Browser mitels
des Reload-Buttons neu.
Vergessen Sie nicht:
- Klick auf das SVN-Commit-Icon.
Grunt
Nun können Sie auch noch Grunt konfiguerieren. Hier wäre das noch nicht so wichtig, da Grunt auch nicht mehr leistet, als die zuvor getesteten NPM-Skript-Befehle. Allerdings kann man mit Grunt nicht nur webpack, sondern auch noch viele weitere Tools verwalten. Ich persönlich finde es ganz angenehm, well alle Tools mit Hilfe eines einzigen Werkzeugs administirert werden.
Fügen Sie folgende Datei ins Wurzelverzeichnis Ihrer Projektes ein:
gruntfile.js
const webpack = require('webpack'),
webpackConfig = require('./webpack.config.js');
module.exports = function(grunt)
{
// Project configuration.
grunt.initConfig
({
pkg: grunt.file.readJSON('package.json'),
webpack:
{
options: webpackConfig,
bundle:
{
},
compress:
{
plugins:
webpackConfig.plugins.concat
( new webpack.optimize.UglifyJsPlugin({ mangle: true }) )
},
watch:
{
watch: true,
keepalive: true
}
},
});
// Register task(s)
grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['webpack:bundle']);
grunt.registerTask('bundle', ['webpack:bundle']);
grunt.registerTask('compress', ['webpack:compress']);
grunt.registerTask('watch', ['webpack:watch']);
};
Damit stehen Ihnen folgende Grunt-Befehle zur Verfügung:
grunt
bzw.grunt bundle
(entsprichtnpm run bundle
)grunt compress
(entsprichtnpm run compress
)grunt watch
(entsprichtnpm run watch
)
Interessant ist, dass hier die Komprimierung der Zieldatei mit Hilfe des Webpack-Plugins
UglifyJsPlugin
und nicht mit Hilfe der Kommandozeilen-Option -f
erzielt wird.
Diese Plugin bietet viele Optionen, mit denen der Kompressionsvorgang gezielt gesteuert werden kann.
Und noch einmal (sobald alles funktioniert):
- Klick auf das SVN-Commit-Icon.
Quellen
- ↑ Google (Web): Make the Web Faster; Organisation: Google Developers; https://developers.google.com/speed/; Quellengüte: 3 (Web), Kapitel „CSS-Bereitstellung optimieren“, https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery
- ↑ https://webpack.js.org/
- ↑ Google (Web): Make the Web Faster; Organisation: Google Developers; https://developers.google.com/speed/; Quellengüte: 3 (Web), Kapitel „CSS-Bereitstellung optimieren“, https://developers.google.com/speed/docs/insights/BlockingJS
- ↑ webpack: https://webpack.js.org/
- ↑ Grunt: https://gruntjs.com/
- ↑ Babel: https://babeljs.io/
- Kowarschick (MMProg): Wolfgang Kowarschick; Vorlesung „Multimedia-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2018; Quellengüte: 3 (Vorlesung)