<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de-x-formal">
	<id>https://glossar.hs-augsburg.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jostl</id>
	<title>GlossarWiki - Benutzerbeiträge [de-formal]</title>
	<link rel="self" type="application/atom+xml" href="https://glossar.hs-augsburg.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jostl"/>
	<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/Spezial:Beitr%C3%A4ge/Jostl"/>
	<updated>2026-07-18T17:31:15Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2017/18:_GameLoop01&amp;diff=43764</id>
		<title>MMProg: Praktikum: WiSe 2017/18: GameLoop01</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=MMProg:_Praktikum:_WiSe_2017/18:_GameLoop01&amp;diff=43764"/>
		<updated>2017-10-27T15:48:49Z</updated>

		<summary type="html">&lt;p&gt;Jostl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{MMProg:Praktikum:WiSe 2017/18:Menü}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/test/WK_Test01_babel/ SVN-Repository]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==Vorbereitung==&lt;br /&gt;
&lt;br /&gt;
Im SVN-Repository finden Sie zwei WebStorm-Projekte zum Thema GameLoop:&lt;br /&gt;
* [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/game_loop/WK_GameLoop01/ WK_GameLoop01]&lt;br /&gt;
* [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/game_loop/WK_GameLoop02/ WK_GameLoop02]&lt;br /&gt;
&lt;br /&gt;
Sie können diese Projekte folgendermaßen auf Ihrem Rechner installieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;VCS&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Checkout from Version Control&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Subversion&amp;lt;/code&amp;gt;&lt;br /&gt;
* Sofern noch nicht geschehen: Klick auf das grüne Plus-Symbol → Repository URL: &amp;lt;code&amp;gt;https://glossar.hs-augsburg.de/beispiel/tutorium/es6&amp;lt;/code&amp;gt;&lt;br /&gt;
* Klick auf die Pfeilspitze vor diesem Pfad → Klick auf die Pfeilspitze vor &amp;lt;code&amp;gt;game_loop&amp;lt;/code&amp;gt; → Klick &#039;&#039;&#039;auf&#039;&#039;&#039; &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Checkout&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;WK_GameLoop01&amp;lt;/code&amp;gt; dient nur didaktischen Zwecken und wird für diese Praktikumsaufgabe nicht benötigt.)&lt;br /&gt;
* Speichern Sie das Projekt irgendwo auf Ihrem Rechner. &#039;&#039;&#039;Achtung: Speichern Sie das Projekt nicht innerhalb eines anderen Projektes (insbesondere nicht in Ihrem neuen Projekt) oder innerhalb eines Ordners, der bereits unter SVN-Kontrolle steht. Speichern meine Projekte in einem ganz anderen Ordner, der {{zB}} &amp;lt;code&amp;gt;KowaBeispiele&amp;lt;/code&amp;gt; heißen könnte.&#039;&#039;&#039;&lt;br /&gt;
* Öffnen Sie das Projekt und geben Sie im WebStorm-Terminal &amp;lt;code&amp;gt;npm install&amp;lt;/code&amp;gt; (oder kurz &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt;) ein, um alle benötigten Node.js-Module zu installieren.&lt;br /&gt;
&lt;br /&gt;
Machen Sie sich mit den Projekten vertraut. Die Web-Anwendung &amp;lt;code&amp;gt;src/js/app&amp;lt;/code&amp;gt; des zweiten Projektes dient als Ausgangsbasis für diese Praktikumsaufgabe.    &lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel finden Sie diverse Game-Loop-Varianten. Schrittweise werden potentielle&lt;br /&gt;
Probleme behoben. Dieses Projekt verfolgt das didaktische Ziel, Ihnen die Probleme und potentielle&lt;br /&gt;
Lösungen im Zusammenhang mit JavaScript-Animationen zu verdeutlichen.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Beispiel wurde eine einfache Game-Loop-Klasse realisiert, die sie für dieses Praktikum&lt;br /&gt;
nutzen können und sollten. Diese Klasse basiert auf den Ergebnissen des ersten Projektes,&lt;br /&gt;
stellt aber – im Gegensatz zu einigen Web-Anwendungen des ersten Projekt – bislang keine Informationen &lt;br /&gt;
über die aktuelle Frame-Rate bereit. Dies ist aber für diese Praktikumsaufgabe nicht von Interesse.&lt;br /&gt;
&lt;br /&gt;
==Aufgaben==&lt;br /&gt;
&lt;br /&gt;
Laden Sie das leere Projekt [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/empty/WK_GameLoop02_Empty WK_GameLoop02_Empty] auf Ihren Rechner&lt;br /&gt;
(am Besten in den zuvor angelegten Ordner &amp;lt;code&amp;gt;KowaBeispiele&amp;lt;/code&amp;gt;).&lt;br /&gt;
&#039;&#039;&#039;Installieren Sie diesmal aber nicht die Node.js-Module&#039;&#039;&#039;, das machen Sie später. Sie finden das leere Projekt im zuvor aktivierten &lt;br /&gt;
Repository-Pfad &amp;lt;code&amp;gt;https://glossar.hs-augsburg.de/beispiel/tutorium/es6&amp;lt;/code&amp;gt; im Unterordner &amp;lt;code&amp;gt;empty&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie ein neues Projekt &amp;lt;code&amp;gt;praktikum01&amp;lt;/code&amp;gt; und kopieren Sie die Ordner &amp;lt;code&amp;gt;src&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;web&amp;lt;/code&amp;gt; (samt Inhalt)&lt;br /&gt;
sowie alle Dateien, die Sie im Wurzelverzeichnis des Projektes &amp;lt;code&amp;gt;WK_GameLoop02_Empty&amp;lt;/code&amp;gt;&lt;br /&gt;
finden mittels &amp;lt;code&amp;gt;Crtl-/Apfel-C&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;Crtl-/Apfel-V&amp;lt;/code&amp;gt; in Ihr eigenes Projekt. (Die Frage, ob WebStorm seinen eigenen File Watcher zum&lt;br /&gt;
Übersetzen von ES6-Code in ES5-Code verwenden soll, beantworten Sie bitte mit „No“. Das erledigt Webpack für Sie.)&lt;br /&gt;
&lt;br /&gt;
Nun können Sie in Ihrem eigenen Projekt die benötigten Node.js-Module installieren: &amp;lt;code&amp;gt;npm i&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sie können Ihr Projekt zur Übung auch im Subversion-Repository speichern. Das ist aber nit so wichtig.&lt;br /&gt;
&lt;br /&gt;
In Ihrem Projekt finden Sie nun 10 Web-Anwendungen vor: &amp;lt;code&amp;gt;index01.html&amp;lt;/code&amp;gt; verwendet die gepackte Version von &amp;lt;code&amp;gt;app01.js&amp;lt;/code&amp;gt;,&lt;br /&gt;
die ihrerseits das Spiel &amp;lt;code&amp;gt;game01.js&amp;lt;/code&amp;gt; einbindet. &amp;lt;code&amp;gt;index02.html&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;index03.html&amp;lt;/code&amp;gt; etc. sind analog aufgebaut.&lt;br /&gt;
Wenn Sie irgendeine dieser Anwendungen im Browser öffnen, sehen Sie eine Eule in der linken oberen Bildschirmecke. Diese sollen&lt;br /&gt;
sie auf unterschiedliche Art und Weise animieren. Lösen Sie jede der folgenden Aufgaben in einer der vorgegebenen Apps.&lt;br /&gt;
Scheuen Sie sich nicht davor, eigene Experimente durchzuführen. Wenn die vorgegebenen Apps nicht ausreichen sollten, legen Sie einfach&lt;br /&gt;
noch ein paar an. (Vergessen Sie in diesem Fall nicht, &amp;lt;code&amp;gt;webpack.config.js&amp;lt;/code&amp;gt; entsprechend zu erweitern.)&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie Ihre Lösungen der Aufgabe $i$ in die Datei &amp;lt;code&amp;gt;game&amp;lt;/code&amp;gt;$i$&amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
Am einfachsten ist es, wenn Sie jeweils die Lösung der vorangegangenen Aufgabe kopieren und diese Kopie dann weiterentwickeln.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 1===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie die Eule horizontal vom linken bis zum rechten Fensterrand des Browsers fliegen. &lt;br /&gt;
&lt;br /&gt;
Tipp: http://ryanve.com/lab/dimensions/&lt;br /&gt;
&lt;br /&gt;
Berücksichtigen Sie, dass die Eule 150 Pixel breit ist und das der Ankerpunkt im linken oberen Eck des zugehörigen Bildes liegt. &lt;br /&gt;
Sie müssen daher im Eulen-Objekt auch die Breite der Eule speichern und diese Breite bei der Kollissionserkennung&lt;br /&gt;
und -behandlung berücksichtigen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass Sie zur Lösung dieser Aufgabe einfach die Datei &amp;lt;code&amp;gt;game01.js&amp;lt;/code&amp;gt; anpassen müssen.&lt;br /&gt;
Lassen Sie sich durch den Code der Datei &amp;lt;code&amp;gt;owl.js&amp;lt;/code&amp;gt; aus dem Beispiel &amp;lt;code&amp;gt;WK_GameLoop02&amp;lt;/code&amp;gt; inspirieren.&lt;br /&gt;
(Sie können auch &amp;lt;code&amp;gt;owl_interpolate.js&amp;lt;/code&amp;gt; verwenden, aber das verwirrt Sie vermutlich zurzeit mehr, als dass es &lt;br /&gt;
Inhen nützt.) Eine Reset-Funktion, wie sie im genannten Beispiel definiert wird, brauchen Sie nicht zu implementieren,&lt;br /&gt;
da Sie das „Spiel“ nicht mit Hilfe von irgendwelchen Buttons anhalten und zurücksetzen werden. Dies gilt auch für alle folgenden &lt;br /&gt;
Aufgaben.&lt;br /&gt;
&lt;br /&gt;
Vergessen Sie &amp;lt;code&amp;gt;grunt&amp;lt;/code&amp;gt; oder besser noch &amp;lt;/code&amp;gt;grunt watch&amp;lt;/code&amp;gt; nicht. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 2===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie die Eule nicht waagerecht, sondern in der horizontalen Mitte des Browserfesnters senkrecht von Fenstrrand zu Festerrand fliegen.&lt;br /&gt;
&lt;br /&gt;
Um die Aufgabe zu lösen, müssen Sie für die Eule zusätzlich eine y-Position und eine y-Geschwindigkeit definieren. Die Berechnung der aktuellen y-Position funktioniert&lt;br /&gt;
analog zur Berechnung der aktuellen x-Position. &lt;br /&gt;
&lt;br /&gt;
Vergessen Sie nicht auch die Kollissionserkennung und -behandlung für die beiden Bildschirmseiten &amp;lt;code&amp;gt;top&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;botton&amp;lt;/code&amp;gt;&lt;br /&gt;
zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Und Sie müssen natürlich die Render-Funktion anpassen, sodass die aktuelle y-Position beim Rendern auch berücksichtigt wird. &lt;br /&gt;
&lt;br /&gt;
===Aufgabe 3===&lt;br /&gt;
&lt;br /&gt;
Lassen Sie die Eule von der Browsermitte aus schräg über den Bildschirm fliegen. In x-Richtung soll sie doppelt so schnell sein (200 Pixel/s)&lt;br /&gt;
wie in y-Richtung (100 Pixel/s).&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 4===&lt;br /&gt;
&lt;br /&gt;
Setzen Sie die x-Start-Position der Eule auf &amp;lt;code&amp;gt;-100&amp;lt;/code&amp;gt; und starten Sie die Web-App. Den Effekt, den Sie sehen, nennt&lt;br /&gt;
man [[Kollisionserkennung und -behandlung|Penetration]]. Die Eule hängt in der Wand fest, da Sie in einem Schritt nicht den Kollissionsbereich&lt;br /&gt;
(die linke Wand) verlässt. Daher besteht die Kollission fort und im nächsten Schritt ändert sie wieder ihre Flugrichtung.&lt;br /&gt;
&lt;br /&gt;
Verbessern Sie das, indem Sie die Kollisionserkennung und -behandlung verbessern:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_owl.x &amp;lt;= v_stage.left)&lt;br /&gt;
{&lt;br /&gt;
  v_owl.vx = Math.abs(v_owl.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_owl.x &amp;gt;= v_stage.right - v_owl.width)&lt;br /&gt;
{&lt;br /&gt;
  v_owl.vx = -Math.abs(v_owl.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung analog an. &lt;br /&gt;
&lt;br /&gt;
Sie können und sollten sogar noch einen Schritt weiter gehen und die Eule &lt;br /&gt;
wieder zurück auf die Bühne schieben, wenn Sie in die Wand eingedrungen ist.&lt;br /&gt;
In die Wand einzudringen ist zwar physikalisch nicht möglich, aber leider in&lt;br /&gt;
einer Simulation der physikalischen Welt nur schwer zu vermeiden, da die&lt;br /&gt;
Position nur alle 16,7 ms berechnet wird. War die Eule zu einem Zeitpunkt&lt;br /&gt;
noch vor der Mauer, kann Sie beim nächsten Schritt schon drinnen stecken.&lt;br /&gt;
Insbesondere bei sehr schnellen Objekten kann das dann zu PEnetrations-Effekten führen.&lt;br /&gt;
&lt;br /&gt;
Also schieben Sie die Eule besser zurück auf die Bühne.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
if (v_owl.x &amp;lt;= v_stage.left)&lt;br /&gt;
{&lt;br /&gt;
  v_owl.x = v_stage.left;&lt;br /&gt;
  v_owl.vx = Math.abs(v_owl.vx);&lt;br /&gt;
}&lt;br /&gt;
if (v_owl.x &amp;gt;= v_stage.right - v_owl.width)&lt;br /&gt;
{&lt;br /&gt;
  v_owl.x = v_stage.right - v_owl.width;&lt;br /&gt;
  v_owl.vx = -Math.abs(v_owl.vx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Passen Sie die Kollisionserkennung und -behandlung in y-Richtung wiederum analog an. &lt;br /&gt;
&lt;br /&gt;
===Aufgabe 5===&lt;br /&gt;
&lt;br /&gt;
Ändern Sie die Kollisionserkennung und -behandlung so ab, dass die Eule ausgehend von der linken oberen Fensterecke&lt;br /&gt;
im Uhrzeigersinn sich immer entlang des Fensterrandes bewegt.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte: Hier ist es besonders wichtig, dass Sie die Eule wieder  auf die Bühne zurückbewegen, wenn sie mit einer&lt;br /&gt;
Wand kollidiert. Ansonsten verschwindet die Eule schnell im Nirgendwo.&lt;br /&gt;
&lt;br /&gt;
(Anmerkung: Dies war einmal eine Aufgabe im Rahmen des Prüfungspraktikums, wobei die Lösung zur 3. Aufgabe vorgegeben war.)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 6===&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie diesmal nicht die Lösung von Aufgabe 5, sondern von Aufgabe 4. Im folgenden arbeiten Sie&lt;br /&gt;
wieder mit der normalen Kollissionserkennung und -behandlung. Positionieren Sie die Eule allerdings wieder im linken oberen Eck&lt;br /&gt;
(in Aufgabe 4 hatten Sie sie außerhalb der Bühne platziert).&lt;br /&gt;
&lt;br /&gt;
Die neue Position der Eule berechnet man mit Hilfe der Geschwindigkeit (velocity). Doch auch die&lt;br /&gt;
Geschwindigkeit kann sich ändern. Dazu benötigt man die Beschleunigung (acceleration).&lt;br /&gt;
&lt;br /&gt;
Fügen Sie zu Ihrer Eule zwei weitere Attribute &amp;lt;code&amp;gt;ax&amp;lt;/code&amp;gt; (Beschleunigung in x-Richtung) und &lt;br /&gt;
&amp;lt;code&amp;gt;ay&amp;lt;/code&amp;gt; (Beschleunigung in y-Richtung) hinzu. Setzen Sie die Initialwerte auf&lt;br /&gt;
&amp;lt;code&amp;gt;400&amp;lt;/code&amp;gt; (Pixel pro Sekunde) bzw. &amp;lt;code&amp;gt;200&amp;lt;/code&amp;gt; (Pixel pro Sekunde). Das heißt, Sie möchten,&lt;br /&gt;
dass die Eule in jeder Sekunde um 400 bzw. 200 Pixel pro Sekunde mehr zurücklegt als zuvor.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie jetzt die Web-App starten, beschleunigt die Eule allerdings noch nicht.&lt;br /&gt;
&lt;br /&gt;
In Ihrem Code wird die Position 60 mal pro Sekunde mit Hilfe des folgenden Codes aktualisiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_owl.x += v_owl.vx * p_frac_s;&lt;br /&gt;
v_owl.y += v_owl.vy * p_frac_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit wird zur Position hinzuaddiert. Allerdings ist die Geschwindigkeit&lt;br /&gt;
in Pixeln pro Sekunde angegeben. Die Modellaktualisierung passiert jedoch alle $0,0167$&lt;br /&gt;
Sekunden. In dieser Zei bewegt sich die Eule nur um das $0,0167$-fache (= $1,67$%) der Sekundengeschwindigkeit weiter.&lt;br /&gt;
&lt;br /&gt;
Auf genau dieselbe Weise wird die aktuelle Geschwindigkeit mit Hilfe der Beschleunigung&lt;br /&gt;
berechnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_owl.vx += v_owl.ax * p_frac_s;&lt;br /&gt;
v_owl.vy += v_owl.ay * p_frac_s;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie diesen Code in Ihre Model-Update-Funktion ein und starten Sie die Eule erneut.&lt;br /&gt;
Wenn Sie jetzt Ihre We-App laufen lassen, stellen Sie fest, dass die Eule zunächst beschleunigt,&lt;br /&gt;
nach eine Kollission aber wieder abbremst. NAch der nächsten Kollission beschleunigt sie wieder.&lt;br /&gt;
&lt;br /&gt;
Um diesen Effekt zu vermeiden, müssen Sie jedes mal, wenn Sie bei der Kollissionsbehandlung das Vorzeichen&lt;br /&gt;
der Geschwindigkeit ändern, das Vorzeichen der zugehörigen Beschleunigung analog ändern.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise mus der Code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_owl.vx = -Math.abs(v_owl.vx);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
um&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
v_owl.ax = -Math.abs(v_owl.ax);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ergänzt werden.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 7===&lt;br /&gt;
&lt;br /&gt;
Schreiben Sie die Kollissionsbehandlung so um, dass im Falle einer Kollission der Eule &lt;br /&gt;
mit dem unteren Fensterrand sowohl die Geschwindigkeit als auch die Beschleunigung&lt;br /&gt;
jeweils in x- und in y-Richtung auf Null gesetzt wird. Das heißt, die &lt;br /&gt;
Eule bleibt bei einer Kollision mit dem unteren Rand stehen stehen.&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 8===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie die Eule im linken oberen Eck, geben Sie ihr eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von 0 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 800. (Diese Zahlen sind gut für meinen Monitor geeignet,&lt;br /&gt;
der eine Auflösung von 1600x900 hat. Wenn Sie einen deutlich kleineren oder größeren&lt;br /&gt;
Monitor haben, müssen Sie die Zahlen evtl. anpassen.)&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt die Eule, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 9===&lt;br /&gt;
&lt;br /&gt;
Positionieren Sie die Eule im linken unteren Eck, geben Sie ihr eine Geschwindigkeit von &lt;br /&gt;
300 Pixeln in x-Richtung und von -400 Pixeln in y-Richtung. Die Beschleunigung in x-Richtung beträgt 0,&lt;br /&gt;
die Beschleunigung in y-Richtung 200.&lt;br /&gt;
&lt;br /&gt;
Welche Kurve beschreibt die Eule, wenn Sie die Web-App starten?&lt;br /&gt;
&lt;br /&gt;
Jetzt fehlt nur noch en Gummiband, mit dem Sie die Eule beschleunigen können. :-)&lt;br /&gt;
&lt;br /&gt;
===Aufgabe 10===&lt;br /&gt;
&lt;br /&gt;
Machen Sie eigene Experimente. Bringen Sie {{zB}} die Eule dazu, wie ein Flummi&lt;br /&gt;
zu springen, indem sie ihre Geschwindigkeit in x- und y-Richtung bei einem Bodenkontakt&lt;br /&gt;
um einen gewissen Prozentsatz reduzieren, aber nicht gleich auf null setzen.&lt;br /&gt;
(Die Beschleunigung, die die Erdanziehung simuliert, bleibt die ganze Zeit über gleich).&lt;br /&gt;
Achtung: Bei einem Bodenkontakt, dreht sich das Vorzeichen der y-Geschwindigkeit um, &lt;br /&gt;
das der x-Geschwindigkeit bleibt gleich.&lt;br /&gt;
&lt;br /&gt;
Nervig ist, dass die Eule zum Schluss immer noch ganz leicht hüpft und gar nicht&lt;br /&gt;
zur Ruhe kommt. Vielleicht können Sie auch dieses Problem beheben.&lt;br /&gt;
&lt;br /&gt;
Oder probieren Sie etwas ganz anderes aus.&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jostl</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=HTML5-Tutorium:_JavaScript:_Hello_World_04&amp;diff=43692</id>
		<title>HTML5-Tutorium: JavaScript: Hello World 04</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=HTML5-Tutorium:_JavaScript:_Hello_World_04&amp;diff=43692"/>
		<updated>2017-10-12T21:53:07Z</updated>

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

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

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

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

		<summary type="html">&lt;p&gt;Jostl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{HTML5-Tutorium:JavaScript:HelloWorld:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld02/index.html &amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;],&lt;br /&gt;
[https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld02/index2.html &amp;lt;code&amp;gt;index2.html&amp;lt;/code&amp;gt;]&lt;br /&gt;
([https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld02/ SVN-Repository])&lt;br /&gt;
==Anwendungsfälle (Use Cases)==&lt;br /&gt;
Die Anwendungsfälle ändern sich gegenüber dem ersten Teil des Tutoriums nicht: &lt;br /&gt;
Der einzige Anwendungsfall der Anwendung ist weiterhin die Begrüßung der ganzen Welt, sobald die Anwendung &lt;br /&gt;
ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Allerdings soll die Begrüßung gefälliger gestaltet werden, indem das Layout der Begrüßungsseite&lt;br /&gt;
verbessert wird. Zeichensatz, Schriftgröße, Zeilenabstand etc. werden geändert.&lt;br /&gt;
&lt;br /&gt;
==Erstellen eines neuen Projektes==&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie im selben Ordner wie das Projekt „&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“ ein neues Projekt  „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“:&lt;br /&gt;
&lt;br /&gt;
# Öffnen Sie das Projekt „&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“ in WebStorm.&lt;br /&gt;
#  &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;New&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Project...&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Empty Project&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tragen Sie den korrekten Projektpfad (mit dem Namen „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ anstelle von „&amp;lt;code&amp;gt;untitled&amp;lt;/code&amp;gt;“ am Pfadende) in dem Feld „&amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt;“ ein.&lt;br /&gt;
# &amp;lt;code&amp;gt;Create&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;New Window&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie nun das neue Projekt in Ihr Subversion-Repository ein (analog zu [[HTML5-Tutorium:_JavaScript:_Hello_World_01|Teil 1]] des Tutoriums)&lt;br /&gt;
und committen Sie (vergessen Sie nicht die Commit Message „&amp;lt;code&amp;gt;Project HelloWorld02 created.&amp;lt;/code&amp;gt;“).&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ aus dem WebStorm01-Projekt in das WebStorm02-Projekt.&lt;br /&gt;
Das können Sie entweder mit dem Dateibrowser Ihrer Wahl machen oder Sie legen die WebStorm-Fenster der Projekte&lt;br /&gt;
„&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“ und „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ nebeneinander, markieren und kopieren „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“&lt;br /&gt;
im ersten Projekt und fügen es in den Dateibaum des zweiten Projektes ein.&lt;br /&gt;
&lt;br /&gt;
Passen Sie den Wert des &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;-Elements im HTML-Header an („&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ anstelle von „&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“).&lt;br /&gt;
&lt;br /&gt;
Überprüfen Sie, ob die Anwendung korrekt gestartet werden kann (Test). Falls dies der Fall ist,&lt;br /&gt;
committen Sie die neue Anwendung (Commit Message: „&amp;lt;code&amp;gt;Files of HelloWorld01 copied.&amp;lt;/code&amp;gt;“)&lt;br /&gt;
&lt;br /&gt;
==Festlegen des Designs der Anwendung==&lt;br /&gt;
&lt;br /&gt;
Nun wird das Design der Anwendung verbessert. Die Überschrift soll in einem &lt;br /&gt;
serifenlosen Font dargestellt werden, der Text des nachfolgenden Absatzes &lt;br /&gt;
in einem serifenhaltigen.&lt;br /&gt;
  &lt;br /&gt;
Die ist kein [[CSS]]-Tutorium, daher wird nicht darauf eingegangen, wie ein geeigneter Font gewählt werden sollte.&lt;br /&gt;
Wir überlassen das einfach dem jeweiligen Browser-Hersteller, indem wir die Pseudofonts&lt;br /&gt;
„&amp;lt;code&amp;gt;sans-serif&amp;lt;/code&amp;gt;“ und „&amp;lt;code&amp;gt;serif&amp;lt;/code&amp;gt;“ angeben. Für [[Mac]]-User wird die Überschrift vermutlich in [[Helvetica]]&lt;br /&gt;
gesetzt und für [[Windows]]-Benutzer in [[Arial]].&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie eine [[CSS]]-Datei:&lt;br /&gt;
&lt;br /&gt;
# Rechtsklick auf die Wurzel „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ des Dateibaums → &amp;lt;code&amp;gt;New&amp;lt;/code&amp;gt;  → &amp;lt;code&amp;gt;Stylesheet&amp;lt;/code&amp;gt;&lt;br /&gt;
# Name: &amp;lt;code&amp;gt;main.css&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;OK&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird eine neue (diesmal leere!) Datei namens „&amp;lt;code&amp;gt;main.css&amp;lt;/code&amp;gt;“ angelegt.&lt;br /&gt;
&lt;br /&gt;
Fügen Sie in diese Datei folgenden CSS-Code ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
h1 &lt;br /&gt;
{ &lt;br /&gt;
  font-family: sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p&lt;br /&gt;
{ &lt;br /&gt;
  font-family: serif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Achten Sie darauf, dass öffnende und zugehörige schließende Klammern stets übereinander oder in derselben Zeile stehen.&lt;br /&gt;
Wenn Sie andere Tutorien bearbeiten, Fachbücher lesen oder Voreinstellungen von Web-IDEs begutachten,&lt;br /&gt;
werden Sie meist folgende Art der Formatierung entdecken, die gegen diese Regel verstößt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* *** DON&#039;T DO IT THAT WAY!!!! *** */&lt;br /&gt;
&lt;br /&gt;
h1 { &lt;br /&gt;
  font-family: sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p { &lt;br /&gt;
  font-family: serif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Begründung lautet dann oft, dass dieser Code weniger Zeilen habe, als der obige Code.&lt;br /&gt;
Das stimmt, lässt sich aber auch ohne Verletzung der Regel „Zusammengehörige Klammern befinden sich in derselben Spalte“&lt;br /&gt;
erreichen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
h1 &lt;br /&gt;
{ font-family: sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p &lt;br /&gt;
{ font-family: serif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Falle von CSS-Code macht es keinen wirklichen Unterschied, welcher Konvention sie folgen.&lt;br /&gt;
&#039;&#039;&#039;Im Falle von JavaScript rate ich jedoch davon ab, öffnende und schließende Klammern nicht in derselben Spalte zu notieren.&#039;&#039;&#039; &lt;br /&gt;
Glauben Sie einem erfahrenen [[LISP]]-Programmierer&lt;br /&gt;
(LISP ist die Sprache, bei der &#039;&#039;jeder&#039;&#039; nicht-atomare Programmcode durch Klammern umschlossen wird):&lt;br /&gt;
Code ist wesentlich besser zu lesen, wenn öffnende und schließende Klammern übereinander stehen.&lt;br /&gt;
Insbesondere Strukturfehler sind bei dieser Konvention wesentlich einfacher zu finden.&lt;br /&gt;
Ob Sie die öffnende Klammer jeweils in einer eigenen Zeile schreiben oder nicht, ist dabei weniger wichtig.&lt;br /&gt;
&lt;br /&gt;
Glücklicherweise highlighten die meisten Editoren (wie beispielsweise die WebStrom-Editoren)&lt;br /&gt;
die zugehörige schließende oder öffnende Klammer, wenn man den Cursor auf (bzw. vor oder nach)&lt;br /&gt;
eine öffnende oder schließende setzt. So erkennt man Strukturfehler auch dann, wenn man bei der&lt;br /&gt;
Einrückung Fehler gemacht hat. (Derartige Fehler sollte man allerdings möglichst schnell beheben,&lt;br /&gt;
wenn man sie einmal entdeckt hat.)&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre CSS-Datei fertiggestellt haben und die Anwendung erneut testen&lt;br /&gt;
({{dh}} die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ im Browser vom WebStorm-Server laden), werden Sie feststellen,&lt;br /&gt;
dass sich nichts geändert hat (auch wenn Sie den Reload-Button des Browsers drücken).&lt;br /&gt;
&lt;br /&gt;
Sie können die CSS-Datei direkt im Browser laden (ersetzen sie in dem Browser-URI einfach „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ durch „&amp;lt;code&amp;gt;main.css&amp;lt;/code&amp;gt;“&lt;br /&gt;
und drücken Sie den Reload-Button), aber das hilft auch nichts. Ihnen wird daraufhin einfach der Inhalt des CSS-Datei vom Browser angezeigt.&lt;br /&gt;
&lt;br /&gt;
Der Grund ist, dass der Browser beim Laden der HTML-Datei nicht weiß, dass er den Inhalt mit Hilfe&lt;br /&gt;
der CSS-Datei layouten soll. Damit er dies weiß, muss folgende Zeile in den  &amp;lt;code&amp;gt;head&amp;lt;/code&amp;gt;-Bereich &lt;br /&gt;
der HTML-Datei eingefügt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;main.css&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Wenn Sie jetzt noch einmal Ihre Web-Anwendung testen, wird die &lt;br /&gt;
Überschrift (evtl. nach einem Klick auf den Reload-Button des Browsers)&lt;br /&gt;
tatsächlich in einer serifenlosen Schriftart dargestellt.&lt;br /&gt;
&lt;br /&gt;
Sie können jetzt noch weitere Verbesserungen vornehmen: Anpassung der Schriftgröße,&lt;br /&gt;
Anpassung des Abstandes zwischen Überschrift und Absatz, Anpassung der Schriftfarbe, &lt;br /&gt;
des Seitenhintergrundes etc. pp.&lt;br /&gt;
&lt;br /&gt;
Zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
html, body&lt;br /&gt;
{&lt;br /&gt;
  height: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
html&lt;br /&gt;
{&lt;br /&gt;
  display: table;&lt;br /&gt;
  width:   100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body&lt;br /&gt;
{&lt;br /&gt;
  display:          table-cell;&lt;br /&gt;
  text-align:       center;&lt;br /&gt;
  vertical-align:   middle;&lt;br /&gt;
  background-color: #C5EFFC; /* zartes Blau */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
h1&lt;br /&gt;
{&lt;br /&gt;
  font-family:    sans-serif;&lt;br /&gt;
  font-size:      160%;&lt;br /&gt;
  padding-bottom: 0;&lt;br /&gt;
  margin-bottom:  0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p&lt;br /&gt;
{&lt;br /&gt;
  font-family:    serif;&lt;br /&gt;
  font-size:      100%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Spielen Sie mit den CSS-Attributen und testen Sie Ihre Anwendung. &lt;br /&gt;
&lt;br /&gt;
Tipp: Mit der CSS-Regel&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
* { border: solid 1px red; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
können Sie sehr einfach den Effekt von Padding-Attribut-Werten überprüfen. Falls Sie Ränder um einige Ihrer&lt;br /&gt;
Elemente zeichnen, sollten Sie &lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
* { outline: solid 1px red; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
verwenden. Wenn Sie mit der Überprüfung fertig sind, sollten Sie diese Befehle allerdings wieder aus&lt;br /&gt;
der CSS-Datei entfernen oder sie zumindest auskommentieren (&amp;lt;code&amp;gt;/* .... */&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie schließlich mit dem Layout Ihrer Anwendung zufrieden sind, committen Sie sie (Commit Message: „&amp;lt;code&amp;gt;Styling for web app was added.&amp;lt;/code&amp;gt;“) .&lt;br /&gt;
&lt;br /&gt;
==Optimierung des Designs für mobile Endgeräte==&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie die Web-Anwendung mit einem Smartphone.&lt;br /&gt;
Da der Zugriff auf den WebStorm-Servers auf Ihrem Entwicklungsrechner eingeschränkt ist, &lt;br /&gt;
müssen Sie Ihre Anwendung auf eine echten Web-Server legen, um mit einem anderen Device darauf zugreifen zu können.&lt;br /&gt;
Falls Sie am Praktikum zur Lehrveranstaltung [[Lehrveranstaltung:IAM 2006:Multimedia-Anwendungen/Programmierung|MMProg]] teilnehmen,&lt;br /&gt;
liegt Ihre Anwendung bereits auf einem externen Server: in Ihrem Subversion-Repository.&lt;br /&gt;
Sie brauchen also nichts weiter zu machen, als zunächst den folgenden URI in Ihrem Smartphone zu öffnen &lt;br /&gt;
(wobei Sie „&amp;lt;code&amp;gt;ACCOUNT&amp;lt;/code&amp;gt;“ durch Ihren RZ-Account ersetzen müssen):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source  lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
https://praktikum.multimedia.hs-augsburg.de/svn/ACCOUNT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dann der Reihe nach alle Unterordner, bis Sie die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ des Projektes „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ finden.&lt;br /&gt;
Wenn Sie sich an die Vorgaben des Tutoriums gehalten haben, wären das zunächst der Ordner „&amp;lt;code&amp;gt;mmprog&amp;lt;/code&amp;gt;“, dann „&amp;lt;code&amp;gt;hello_world&amp;lt;/code&amp;gt;“&lt;br /&gt;
und schließlich „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie nun die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ öffnen, werden Sie feststellen, dass die Schrift viel zu klein ist und der Begrüßungstext daher&lt;br /&gt;
nur schwer gelesen werden kann. Der Grund ist, dass die mobilen Browser in der Regel genauso rendern wie stationäre Browser. Da der Bildschirm aber viel kleiner&lt;br /&gt;
ist, erkennt man nicht mehr viel.&lt;br /&gt;
&lt;br /&gt;
Unter [[Responsive Webdesign]] versteht man ein gestalterisches Paradigma, welches zum Ziel hat, eine Web-Site auf jedem möglichen Endgerät möglichst optimal les-&lt;br /&gt;
und benutzbar darzustellen. Technische Basis ist hier vor allem [[CSS]], aber natürlich auch [[HTML5]] und [[JavaScript]].&lt;br /&gt;
&lt;br /&gt;
In unserem Fall reicht es, ein weiteres Meta-Tag in den HTML-Header einzufügen, &lt;br /&gt;
das den Browser anweist, für die Darstellung der HTML-Body-Elemente eine Bühne zu verwenden, die genauso breit ist, &lt;br /&gt;
wie das Fenster des Devices (PC, Tablet im Querformat, Smartphone im Hochformat etc.) .&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name    = &amp;quot;viewport&amp;quot;&lt;br /&gt;
      content = &amp;quot;width=device-width, initial-scale=1.0, user-scalable=yes&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus wird dem Browser mitgeteilt, das der Benutzer die Größe ändern kann (per Touchgeste). Initial&lt;br /&gt;
beträgt die Größe 100% (= 1,0).&lt;br /&gt;
&lt;br /&gt;
Wenn alles funktioniert, committen Sie sie (Commit Message: „&amp;lt;code&amp;gt;Support for mobile devices added.&amp;lt;/code&amp;gt;“) .&lt;br /&gt;
&lt;br /&gt;
==Fortsetzung des Tutoriums==&lt;br /&gt;
&lt;br /&gt;
Sie sollten nun [[HTML5-Tutorium: JavaScript: Hello World 03|Teil 3 des Tutoriums]] bearbeiten.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Kategorie: HTML5-Tutorium: JavaScript: Hello World]][[Kategorie: HTML5-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jostl</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=HTML5-Tutorium:_JavaScript:_Hello_World_02&amp;diff=43687</id>
		<title>HTML5-Tutorium: JavaScript: Hello World 02</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=HTML5-Tutorium:_JavaScript:_Hello_World_02&amp;diff=43687"/>
		<updated>2017-10-12T20:02:39Z</updated>

		<summary type="html">&lt;p&gt;Jostl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{HTML5-Tutorium:JavaScript:HelloWorld:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld02/index.html &amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;],&lt;br /&gt;
[https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld02/index2.html &amp;lt;code&amp;gt;index2.html&amp;lt;/code&amp;gt;]&lt;br /&gt;
([https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld02/ SVN-Repository])&lt;br /&gt;
==Anwendungsfälle (Use Cases)==&lt;br /&gt;
Die Anwendungsfälle ändern sich gegenüber dem ersten Teil des Tutoriums nicht: &lt;br /&gt;
Der einzige Anwendungsfall der Anwendung ist weiterhin die Begrüßung der ganzen Welt, sobald die Anwendung &lt;br /&gt;
ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Allerdings soll die Begrüßung gefälliger gestaltet werden, indem das Layout der Begrüßungsseite&lt;br /&gt;
verbessert wird. Zeichensatz, Schriftgröße, Zeilenabstand etc. werden geändert.&lt;br /&gt;
&lt;br /&gt;
==Erstellen eines neuen Projektes==&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie im selben Ordner wie das Projekt „&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“ ein neues Projekt  „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“:&lt;br /&gt;
&lt;br /&gt;
# Öffnen Sie das Projekt „&amp;lt;code&amp;gt;HellowWorld01&amp;lt;/code&amp;gt;“ in WebStorm.&lt;br /&gt;
#  &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;New&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Project...&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Empty Project&amp;lt;/code&amp;gt;&lt;br /&gt;
# Tragen Sie den korrekten Projektpfad (mit dem Namen „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ anstelle von „&amp;lt;code&amp;gt;untitled&amp;lt;/code&amp;gt;“ am Pfadende) in dem Feld „&amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt;“ ein.&lt;br /&gt;
# &amp;lt;code&amp;gt;Create&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;New Window&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie nun das neue Projekt in Ihr Subversion-Repository ein (analog zu [[HTML5-Tutorium:_JavaScript:_Hello_World_01|Teil 1]] des Tutoriums)&lt;br /&gt;
und committen Sie (vergessen Sie nicht die Commit Message „&amp;lt;code&amp;gt;Project HelloWorld02 created.&amp;lt;/code&amp;gt;“).&lt;br /&gt;
&lt;br /&gt;
Kopieren Sie die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ aus dem WebStorm01-Projekt in das WebStorm02-Projekt.&lt;br /&gt;
Das können Sie entweder mit dem Dateibrowser Ihrer Wahl machen oder Sie legen die WebStorm-Fenster der Projekte&lt;br /&gt;
„&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“ und „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ nebeneinander, markieren und kopieren „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“&lt;br /&gt;
im ersten Projekt und fügen es in den Dateibaum des zweiten Projektes ein.&lt;br /&gt;
&lt;br /&gt;
Passen Sie den Wert des &amp;lt;code&amp;gt;title&amp;lt;/code&amp;gt;-Elements im HTML-Header an („&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ anstelle von „&amp;lt;code&amp;gt;HelloWorld01&amp;lt;/code&amp;gt;“).&lt;br /&gt;
&lt;br /&gt;
Überprüfen Sie, ob die Anwendung korrekt gestartet werden kann (Test). Falls dies der Fall ist,&lt;br /&gt;
committen Sie die neue Anwendung (Commit Message: „&amp;lt;code&amp;gt;Files of HelloWorld01 copied.&amp;lt;/code&amp;gt;“)&lt;br /&gt;
&lt;br /&gt;
==Festlegen des Designs der Anwendung==&lt;br /&gt;
&lt;br /&gt;
Nun wird das Design der Anwendung verbessert. Die Überschrift soll in einem &lt;br /&gt;
serifenlosen Font dargestellt werden, der Text des nachfolgenden Absatzes &lt;br /&gt;
in einem serifenhaltigen.&lt;br /&gt;
  &lt;br /&gt;
Die ist kein [[CSS]]-Tutorium, daher wird nicht darauf eingegangen, wie ein geeigneter Font gewählt werden sollte.&lt;br /&gt;
Wir überlassen das einfach dem jeweiligen Browser-Hersteller, indem wir die Pseudofonts&lt;br /&gt;
„&amp;lt;code&amp;gt;sans-serif&amp;lt;/code&amp;gt;“ und „&amp;lt;code&amp;gt;serif&amp;lt;/code&amp;gt;“ angeben. Für [[Mac]]-User wird die Überschrift vermutlich in [[Helvetica]]&lt;br /&gt;
gesetzt und für [[Windows]]-Benutzer in [[Arial]].&lt;br /&gt;
&lt;br /&gt;
Erstellen Sie eine [[CSS]]-Datei:&lt;br /&gt;
&lt;br /&gt;
# Rechtsklick auf die Wurzel „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ des Dateibaums → &amp;lt;code&amp;gt;New&amp;lt;/code&amp;gt;  → &amp;lt;code&amp;gt;Stylesheet&amp;lt;/code&amp;gt;&lt;br /&gt;
# Name: &amp;lt;code&amp;gt;main.css&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;OK&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird eine neue (diesmal leere!) Datei namens „&amp;lt;code&amp;gt;main.css&amp;lt;/code&amp;gt;“ angelegt.&lt;br /&gt;
&lt;br /&gt;
Fügen Sie in diese Datei folgenden CSS-Code ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
h1 &lt;br /&gt;
{ &lt;br /&gt;
  font-family: sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p&lt;br /&gt;
{ &lt;br /&gt;
  font-family: serif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Achten Sie darauf, dass öffnende und zugehörige schließende Klammern stets übereinander oder in derselben Zeile stehen.&lt;br /&gt;
Wenn Sie andere Tutorien bearbeiten, Fachbücher lesen oder Voreinstellungen von Web-IDEs begutachten,&lt;br /&gt;
werden Sie meist folgende Art der Formatierung entdecken, die gegen diese Regel verstößt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
/* *** DON&#039;T DO IT THAT WAY!!!! *** */&lt;br /&gt;
&lt;br /&gt;
h1 { &lt;br /&gt;
  font-family: sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p { &lt;br /&gt;
  font-family: serif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Begründung lautet dann oft, dass dieser Code weniger Zeilen habe, als der obige Code.&lt;br /&gt;
Das stimmt, lässt sich aber auch ohne Verletzung der Regel „Zusammengehörige Klammern befinden sich in derselben Spalte“&lt;br /&gt;
erreichen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
h1 &lt;br /&gt;
{ font-family: sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p &lt;br /&gt;
{ font-family: serif;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Falle von CSS-Code macht es keinen wirklichen Unterschied, welcher Konvention sie folgen.&lt;br /&gt;
&#039;&#039;&#039;Im Falle von JavaScript rate ich jedoch davon ab, öffnende und schließende Klammern nicht in derselben Spalte zu notieren.&#039;&#039;&#039; &lt;br /&gt;
Glauben Sie einem erfahrenen [[LISP]]-Programmierer&lt;br /&gt;
(LISP ist die Sprache, bei der &#039;&#039;jeder&#039;&#039; nicht-atomare Programmcode durch Klammern umschlossen wird):&lt;br /&gt;
Code ist wesentlich besser zu lesen, wenn öffnende und schließende Klammern übereinander stehen.&lt;br /&gt;
Insbesondere Strukturfehler sind bei dieser Konvention wesentlich einfacher zu finden.&lt;br /&gt;
Ob Sie die öffnende Klammer jeweils in einer eigenen Zeile schreiben oder nicht, ist dabei weniger wichtig.&lt;br /&gt;
&lt;br /&gt;
Glücklicherweise highlighten die meisten Editoren (wie beispielsweise die WebStrom-Editoren)&lt;br /&gt;
die zugehörige schließende oder öffnende Klammer, wenn man den Cursor auf (bzw. vor oder nach)&lt;br /&gt;
eine öffnende oder schließende setzt. So erkennt man Strukturfehler auch dann, wenn man bei der&lt;br /&gt;
Einrückung Fehler gemacht hat. (Derartige Fehler sollte man allerdings möglichst schnell beheben,&lt;br /&gt;
wenn man sie einmal entdeckt hat.)&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre CSS-Datei fertiggestellt haben und die Anwendung erneut testen&lt;br /&gt;
({{dh}} die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ im Browser vom WebStorm-Server laden), werden Sie feststellen,&lt;br /&gt;
dass sich nichts geändert hat (auch wenn Sie den Reload-Button des Browsers drücken).&lt;br /&gt;
&lt;br /&gt;
Sie können die CSS-Datei direkt im Browser laden (ersetzen sie in dem Browser-URI einfach „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ durch „&amp;lt;code&amp;gt;main.css&amp;lt;/code&amp;gt;“&lt;br /&gt;
und drücken Sie den Reload-Button), aber das hilft auch nichts. Ihnen wird daraufhin einfach der Inhalt des CSS-Datei vom Browser angezeigt.&lt;br /&gt;
&lt;br /&gt;
Der Grund ist, dass der Browser beim Laden der HTML-Datei nicht weiß, dass er den Inhalt mit Hilfe&lt;br /&gt;
der CSS-Datei layouten soll. Damit er dies weiß, muss folgende Zeile in den  &amp;lt;code&amp;gt;head&amp;lt;/code&amp;gt;-Bereich &lt;br /&gt;
der HTML-Datei eingefügt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;main.css&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Wenn Sie jetzt noch einmal Ihre Web-Anwendung testen, wird die &lt;br /&gt;
Überschrift (evtl. nach einem Klick auf den Reload-Button des Browsers)&lt;br /&gt;
tatsächlich in einer serifenlosen Schriftart dargestellt.&lt;br /&gt;
&lt;br /&gt;
Sie können jetzt noch weitere Verbesserungen vornehmen: Anpassung der Schriftgröße,&lt;br /&gt;
Anpassung des Abstandes zwischen Überschrift und Absatz, Anpassung der Schriftfarbe, &lt;br /&gt;
des Seitenhintergrundes etc. pp.&lt;br /&gt;
&lt;br /&gt;
Zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
html, body&lt;br /&gt;
{&lt;br /&gt;
  height: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
html&lt;br /&gt;
{&lt;br /&gt;
  display: table;&lt;br /&gt;
  width:   100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body&lt;br /&gt;
{&lt;br /&gt;
  display:          table-cell;&lt;br /&gt;
  text-align:       center;&lt;br /&gt;
  vertical-align:   middle;&lt;br /&gt;
  background-color: #C5EFFC; /* zartes Blau */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
h1&lt;br /&gt;
{&lt;br /&gt;
  font-family:    sans-serif;&lt;br /&gt;
  font-size:      160%;&lt;br /&gt;
  padding-bottom: 0;&lt;br /&gt;
  margin-bottom:  0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
p&lt;br /&gt;
{&lt;br /&gt;
  font-family:    serif;&lt;br /&gt;
  font-size:      100%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Spielen Sie mit den CSS-Attributen und testen Sie Ihre Anwendung. &lt;br /&gt;
&lt;br /&gt;
Tipp: Mit der CSS-Regel&lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
* { border: solid 1px red; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
können Sie sehr einfach den Effekt von Padding-Attribut-Werten überprüfen. Falls Sie Ränder um einige Ihrer&lt;br /&gt;
Elemente zeichnen, sollten Sie &lt;br /&gt;
&amp;lt;source lang=&amp;quot;css&amp;quot;&amp;gt;&lt;br /&gt;
* { outline: solid 1px red; }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
verwenden. Wenn Sie mit der Überprüfung fertig sind, sollten Sie diese Befehle allerdings wieder aus&lt;br /&gt;
der CSS-Datei entfernen oder sie zumindest auskommentieren (&amp;lt;code&amp;gt;/* .... */&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie schließlich mit dem Layout Ihrer Anwendung zufrieden sind, committen Sie sie (Commit Message: „&amp;lt;code&amp;gt;Styling for web app was added.&amp;lt;/code&amp;gt;“) .&lt;br /&gt;
&lt;br /&gt;
==Optimierung des Designs für mobile Endgeräte==&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie die Web-Anwendung mit einem Smartphone.&lt;br /&gt;
Da der Zugriff auf den WebStorm-Servers auf Ihrem Entwicklungsrechner eingeschränkt ist, &lt;br /&gt;
müssen Sie Ihre Anwendung auf eine echten Web-Server legen, um mit einem anderen Device darauf zugreifen zu können.&lt;br /&gt;
Falls Sie am Praktikum zur Lehrveranstaltung [[Lehrveranstaltung:IAM 2006:Multimedia-Anwendungen/Programmierung|MMProg]] teilnehmen,&lt;br /&gt;
liegt Ihre Anwendung bereits auf einem externen Server: in Ihrem Subversion-Repository.&lt;br /&gt;
Sie brauchen also nichts weiter zu machen, als zunächst den folgenden URI in Ihrem Smartphone zu öffnen &lt;br /&gt;
(wobei Sie „&amp;lt;code&amp;gt;ACCOUNT&amp;lt;/code&amp;gt;“ durch Ihren RZ-Account ersetzen müssen):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source  lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
https://praktikum.multimedia.hs-augsburg.de/svn/ACCOUNT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie dann der Reihe nach alle Unterordner, bis Sie die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ des Projektes „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“ finden.&lt;br /&gt;
Wenn Sie sich an die Vorgaben des Tutoriums gehalten haben, wären das zunächst der Ordner „&amp;lt;code&amp;gt;mmprog&amp;lt;/code&amp;gt;“, dann „&amp;lt;code&amp;gt;hello_world&amp;lt;/code&amp;gt;“&lt;br /&gt;
und schließlich „&amp;lt;code&amp;gt;HelloWorld02&amp;lt;/code&amp;gt;“.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie nun die Datei „&amp;lt;code&amp;gt;index.html&amp;lt;/code&amp;gt;“ öffnen, werden Sie feststellen, dass die Schrift viel zu klein ist und der Begrüßungstext daher&lt;br /&gt;
nur schwer gelesen werden kann. Der Grund ist, dass die mobilen Browser in der Regel genauso rendern wie stationäre Browser. Da der Bildschirm aber viel kleiner&lt;br /&gt;
ist, erkennt man nicht mehr viel.&lt;br /&gt;
&lt;br /&gt;
Unter [[Responsive Webdesign]] versteht man ein gestalterisches Paradigma, welches zum Ziel hat, eine Web-Site auf jedem möglichen Endgerät möglichst optimal les-&lt;br /&gt;
und benutzbar darzustellen. Technische Basis ist hier vor allem [[CSS]], aber natürlich auch [[HTML5]] und [[JavaScript]].&lt;br /&gt;
&lt;br /&gt;
In unserem Fall reicht es, ein weiteres Meta-Tag in den HTML-Header einzufügen, &lt;br /&gt;
das den Browser anweist, für die Darstellung der HTML-Body-Elemente eine Bühne zu verwenden, die genauso breit ist, &lt;br /&gt;
wie das Fenster des Devices (PC, Tablet im Querformat, Smartphone im Hochformat etc.) .&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;meta name    = &amp;quot;viewport&amp;quot;&lt;br /&gt;
      content = &amp;quot;width=device-width, initial-scale=1.0, user-scalable=yes&amp;quot;&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus wird dem Browser mitgeteilt, das der Benutzer die Größe ändern kann (per Touchgeste). Initial&lt;br /&gt;
beträgt die Größe 100% (= 1,0).&lt;br /&gt;
&lt;br /&gt;
Wenn alles funktioniert, committen Sie sie (Commit Message: „&amp;lt;code&amp;gt;Support for mobile devices added.&amp;lt;/code&amp;gt;“) .&lt;br /&gt;
&lt;br /&gt;
==Fortsetzung des Tutoriums==&lt;br /&gt;
&lt;br /&gt;
Sie sollten nun [[HTML5-Tutorium: JavaScript: Hello World 03|Teil 3 des Tutoriums]] bearbeiten.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;1&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Kategorie: HTML5-Tutorium: JavaScript: Hello World]][[Kategorie: HTML5-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jostl</name></author>
	</entry>
	<entry>
		<id>https://glossar.hs-augsburg.de/w/index.php?title=HTML5-Tutorium:_JavaScript:_Entwicklungsumgebung:_Node.js&amp;diff=43686</id>
		<title>HTML5-Tutorium: JavaScript: Entwicklungsumgebung: Node.js</title>
		<link rel="alternate" type="text/html" href="https://glossar.hs-augsburg.de/w/index.php?title=HTML5-Tutorium:_JavaScript:_Entwicklungsumgebung:_Node.js&amp;diff=43686"/>
		<updated>2017-10-12T19:07:07Z</updated>

		<summary type="html">&lt;p&gt;Jostl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{HTML5-Tutorium:JavaScript:Entwicklungsumgebung:Menü}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Musterlösung&#039;&#039;&#039;: [https://glossar.hs-augsburg.de/beispiel/tutorium/es6/test/WK_Test01_babel/ SVN-Repository]&lt;br /&gt;
&lt;br /&gt;
Zur Unterstützung der Entwicklung von Web-Anwendungen kann [[Node.js]]&amp;lt;ref&amp;gt;Node.js: https://nodejs.org/en/&amp;lt;/ref&amp;gt; eingesetzt werden: &lt;br /&gt;
automatische Übersetzung von [[ECMAScript|ECMAScript 6/7/8]] (genauer ECMAScript 2015/2016/2017) in ECMAScript 5.1, automatische Generierung der&lt;br /&gt;
Dokumentation, automatisches Testen der Anwendung etc.&lt;br /&gt;
&lt;br /&gt;
Das heißt, auch wenn man keine Node.js-Server-Anwendung erstellt, ist Node.js ein &lt;br /&gt;
sehr wertvolles und universell einsetzbares Werkzeug.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===Unix-Shell===&lt;br /&gt;
Web-Entwickler verwenden unter Windows {{iAllg}} ein Terminal, das eine [[Unix]]-[[Shell]] simuliert.&lt;br /&gt;
Unter Linux und Mac OS X ist es nicht notwendig, eine separate Unix-Shell zu installieren, da&lt;br /&gt;
diese dort sowieso schon existiert (Unix: bash, Mac OS X: terminal).&lt;br /&gt;
&lt;br /&gt;
Installieren Sie „Git for Windows“ (&amp;lt;code&amp;gt;https://git-for-windows.github.io/&amp;lt;/code&amp;gt;; wählen Sie bei jeder Frage die Default-Werte, außer Sie haben einen triftigen Grund, davon abzuweichen). In diesem Paket ist die „Git BASH“ enthalten.&lt;br /&gt;
Das ist eine Terminal-Anwendung, die eine Linux-Bash emuliert und zahlreiche nützliche Befehle wie &amp;lt;code&amp;gt;which&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[vi]]&amp;lt;/code&amp;gt; ( :-) ) etc. zur&lt;br /&gt;
Verfügung stellt.&lt;br /&gt;
&lt;br /&gt;
Unter [[HTML5-Tutorium: JavaScript: Entwicklungsumgebung: WebStorm|WebStorm]] steht ebenfalls ein Terminal zur Verfügung, &lt;br /&gt;
in dem Sie Kommandozeilen-Befehle absetzen können:&lt;br /&gt;
* Menü am unteren Festerrand: Klick auf &amp;lt;code&amp;gt;Terminal&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn Sie das Web-Storm-Terminal verwenden, befinden Sie sich automatisch im Wurzelverzeichnis des zugehörigen Projektes. &lt;br /&gt;
Bei Im Allgemeinen müssen Sie jedoch mit Hilfe des Unix-Befehls &amp;lt;code&amp;gt;cd&amp;amp;nbsp;&amp;amp;lt;PFAD&amp;amp;gt;&amp;lt;/code&amp;gt; in das Wurzelverzeichnis des&lt;br /&gt;
Projektes wechseln, wenn Sie Befehle absetzen wollen, die sich auf ein bestimmtes Projekt beziehen.&lt;br /&gt;
&lt;br /&gt;
Achtung: Unter Windows stehen Ihnen in WebStorm nur die Windows-Kommandozeilen-Befehle zur Verdügung,&lt;br /&gt;
unter Linux und Mac können (und müssen) Sie dort Linux-Kommandozeilen-Befehle eingeben.&lt;br /&gt;
&lt;br /&gt;
===Node.js===&lt;br /&gt;
Installieren Sie nun Node.js: &amp;lt;code&amp;gt;https://nodejs.org/en/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;https://nodejs.org/dist/latest01/&amp;lt;/code&amp;gt;, Version 8.x. &lt;br /&gt;
Achten Sie darauf, dass die Option &amp;lt;code&amp;gt;Add to PATH&amp;lt;/code&amp;gt; ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
Starten Sie ein Unix-Terminal ({{zB}} Mac-OS-X-Terminal, &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt; oder auch WebStorm: Klick auf Icon in der linken unteren Ecke → Klick auf &amp;lt;code&amp;gt;Terminal&amp;lt;/code&amp;gt;).&lt;br /&gt;
Öffnen Sie das Terminal, um zu testen, ob &amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt; funktioniert:&lt;br /&gt;
&lt;br /&gt;
* Geben Sie Folgendes in die Konsole ein: &amp;lt;code&amp;gt;node -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn Node.js korrekt installiert und der Pfad mit den &amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt;-Binaries in die Systemvariable &amp;lt;code&amp;gt;PATH&amp;lt;/code&amp;gt; eingetragen wurde,&lt;br /&gt;
sollte die Versionsnummer von &amp;lt;code&amp;gt;node&amp;lt;/code&amp;gt; ausgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Sie werden feststellen, das Node.js zum Großteil über Terminal-Befehle gesteuert wird. &lt;br /&gt;
Zu Beginn mag das für eingefleischte [[Klickibunti]]-Fans ungewohnt sein, aber Sie werden sich schnell daran gewöhnen.&lt;br /&gt;
&lt;br /&gt;
===Wichtige Node.js-Pakete===&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe von &amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;npm: https://www.npmjs.com/&amp;lt;/ref&amp;gt; (npm = node package manager) können beliebige Node.js-Pakete installiert werden.&lt;br /&gt;
Viele dieser Pakte könnte man global auf dem Rechner installieren.&lt;br /&gt;
Die globale Installation hätte zur Folge, dass jedes Projekt auf diese Pakete zugreifen kann, Pakete also nicht mehrfach installiert werden müssen.&lt;br /&gt;
&lt;br /&gt;
Im Allgemeinen ist es alledings besser, die Pakete für jedes Projekt separat, {{dh}} projektlokal zu installieren. &lt;br /&gt;
Die kostet zwar mehr Platz, hat aber den Vorteil, dass man für verschiedene Projekte verschiedene Pakete verwenden kann. Es kann durchaus sein, dass &lt;br /&gt;
zwei verschiedene Pakete ein drittes benötigen, doch jeweils in einer anderen Version. Außerdem stehen einem anderen Entwickler, der eine Kopie&lt;br /&gt;
Ihres Projektes erhält, dann sofort alle Pakete in der jeweils benötigten Version zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Um ein neues Projekt zu erstellen, legt man zunächst einen leeren Ordner an. Es kann ein beliebiger Ordner gewählt werden.&lt;br /&gt;
Im Folgenden wählen wir &amp;lt;code&amp;gt;/C/mmprog/test01&amp;lt;/code&amp;gt; als Beispielsordner. (Beachten Sie, dass in der GIT Bash wie auch im HTML-Umfeld immer Linux-Pfad-Bezeichner verwendet werden, auch unter Windows.)&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun ihr bevorzugtes Unix-Terminal&lt;br /&gt;
und geben Sie folgenden Befehle ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
                          # Erzeugen Sie ein neues (leeres!) Projektverzeichnis.&lt;br /&gt;
                          # Bitte passen Sie diesen Pfad an Ihre Gegebenheiten an.&lt;br /&gt;
mkdir -p /C/mmprog/test01 # Achten Sie darauf, dass es diesen Pfad vorher nicht gegeben hat.&lt;br /&gt;
cd /C/mmprog/test01       # Hier müssen Sie den von Ihnen zuvor definierten Pfad angeben.  &lt;br /&gt;
npm init -y               # Erzeugen Sie ein neues Node.js-Projekt unter Kontrolle von npm.&lt;br /&gt;
                          # Installieren Sie nun die Node.js-Pakete grunt (Task-Manager) &lt;br /&gt;
                          # und babel (JavaScript-Transpiler) projektlokal.&lt;br /&gt;
npm install --save-dev grunt&lt;br /&gt;
ls -al                    # Sehen Sie sich an, welche Dateien und Ordner erzeugt wurden.&lt;br /&gt;
ls -al node_modules/.bin&lt;br /&gt;
                          # Damit WebStorm den Befehl &#039;node_modules/.bin/grunt&#039; findet,&lt;br /&gt;
                          # muss noch das Grunt-Command-Line-Interface global&lt;br /&gt;
                          # installiert werden. &lt;br /&gt;
npm install -g grunt-cli  # Mac OS X: sudo npm install -g grunt-cli&lt;br /&gt;
less package.json         # Sehen Sie sich den Inhalt der Konfigurationsdatei an.&lt;br /&gt;
                                      # Verlassen von &amp;quot;less&amp;quot;: Taste &amp;quot;q&amp;quot; drücken.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sie können das Projekt in WebStorm öffenen, um die zugehörigen Dateien mit dem&lt;br /&gt;
WebStorm-Editor bearbeiten zu können:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Open&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;WebStorm&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Open&amp;lt;/code&amp;gt;&lt;br /&gt;
* Zum zuvor angelegten Testordner navigieren und diesen mit &amp;lt;code&amp;gt;OK&amp;lt;/code&amp;gt; öffnen. Die Frage, ob Sie das Projekt im selben oder in einem neuen Fenster öffnen wollen, können Sie nach Belieben beantworten. &lt;br /&gt;
&lt;br /&gt;
Sie können Ihre JavaScript-Projekt-Dateien auch mit jedem beliebigen anderen Code-Editor (Atom, Sublime, Nodepad++, Emacs etc. pp.) bearbeiten. &lt;br /&gt;
Das liegt ganz bei Ihnen. WebStorm ist sehr angenehm zu bedienen und enthält einen kleinen Web-Server, der die Entwicklung von JavaScript-Code erleichtert. &lt;br /&gt;
(Es gibt allerdings auch für Node.js einen einfachen HTTP-Server, der bei der Entwicklung von HTML-Anwendungen zu &lt;br /&gt;
Testzwecken eingesetzt werden kann: https://github.com/indexzero/http-server)&lt;br /&gt;
Das Terminalfenster von WebStorm ist auch sehr praktisch. Insbesondere Node.js-Befehle können&lt;br /&gt;
dort direkt eingegeben werden. Unter Windows verwende ich allerdings für komplexere Aufgaben die (Git-)Bash.&lt;br /&gt;
&lt;br /&gt;
Sie sollten sich angewöhnen, in der Datei &amp;lt;code&amp;gt;package.json&amp;lt;/code&amp;gt; sofort nachdem Sie sie&lt;br /&gt;
erstellt haben, ein paar projektspezifische Informationen zu ergänzen, wobei Sie die Werte&lt;br /&gt;
natürlich an Ihre Gegebenheiten anpassen müssen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;quot;keywords&amp;quot;: [&amp;quot;test&amp;quot;],&lt;br /&gt;
  &amp;quot;author&amp;quot;: &amp;quot;Wolfgang Kowarschick&amp;quot;,&lt;br /&gt;
  &amp;quot;license&amp;quot;: &amp;quot;CC-BY-NC-SA-4.0&amp;quot;,&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ändern Sie dagegen nicht die Paketinformationen, die im Attribut &amp;lt;code&amp;gt;devDependencies&amp;lt;/code&amp;gt; gespeichert sind.&lt;br /&gt;
Diese werden mittels &amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt; verwaltet.&lt;br /&gt;
Der Node-Paket-Manager &amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt; ist ein sehr nützliches Hilfsprogramm,&lt;br /&gt;
mit dem Sie neue Node-Projekte erstellen (&amp;lt;code&amp;gt;npm init -y&amp;lt;/code&amp;gt;), Pakete installieren (&amp;lt;code&amp;gt;npm install&amp;lt;/code&amp;gt;) und&lt;br /&gt;
wieder löschen (&amp;lt;code&amp;gt;npm uninstall&amp;lt;/code&amp;gt;) sowie vieles mehr machen können (Dokumentation: https://docs.npmjs.com/).&lt;br /&gt;
&lt;br /&gt;
Wichtig ist auch der Befehl&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm update&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Mit diesem können Sie die lokal gespeicherte Versionen der im Attribut &amp;lt;code&amp;gt;devDependencies&amp;lt;/code&amp;gt; aufgeführte Node.js-Pakete&lt;br /&gt;
jederzeit auf die neueste Version aktualisieren. Die aktuell installierten Versionen können Sie mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm -g list # globale Node.js-Pakete&lt;br /&gt;
npm list    # projektlokale Node.js-Pakete&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
erfragen.&lt;br /&gt;
&lt;br /&gt;
Sie können Pakete auch lokal löschen und dann mittels &amp;lt;code&amp;gt;npm install&amp;lt;/code&amp;gt; wieder herstellen.&lt;br /&gt;
Versuchen Sie es (Achtung: Die Unix-Befehle &amp;lt;code&amp;gt;ls&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;rm&amp;lt;/code&amp;gt; funktionieren &lt;br /&gt;
unter Windows nur in der Bash. In einem Windows-Terminal heißen die entsprechenden Befehle  &amp;lt;code&amp;gt;dir&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;del&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -al node_modules # Liste alle Dateien und Verzeichnisse auf,&lt;br /&gt;
                    # die im Ordner node_modules enthalten sind.&lt;br /&gt;
rm -rf node_modules # Lösche diesen Ordner samt Inhalt.&lt;br /&gt;
npm list&lt;br /&gt;
ls -al node_modules&lt;br /&gt;
npm install&lt;br /&gt;
ls -al node_modules&lt;br /&gt;
npm list&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sie können auch überprüfen, ob Sie in Ihrem Projekt irgendwelche veralteten Pakete benutzen (https://docs.npmjs.com/cli/outdated):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm outdated    # projektlokale Node.js-Pakete&lt;br /&gt;
npm -g outdated # globale Node.js-Pakete&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kein Ergebnis ist hier ein gutes Ergebnis! Ansonsten sollten die die veralteten Pakete aktualisieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm update    # projektlokale Node.js-Pakete &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei veralteten globalen Paketen, müssen Sie das entsprechende Paket erneut installieren.&lt;br /&gt;
Wenn beispielsweise grunt-cli veraltet ist, schreiben Sie:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm -g install grunt-cli    # Mac OS X: sudo npm -g install grunt-cli&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wurde &amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt; global installiert und ist veraltet, lautet der Befehl entsprechend:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm -g install npm    # Mac OS X: sudo npm -g install npm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Das Tool &amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt; kann sich also selbst aktualisieren. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Node.js-Pakete können, wie wir gesehen haben, mittels der npm-Option &amp;lt;code&amp;gt;-g&amp;lt;/code&amp;gt; auch global gespeichert werden, werden aber normalerweise projektlokal abgelegt.&lt;br /&gt;
Durch die projektlokale Speicherung von Node.js-Paketen bläht sich ein Projekt sehr stark auf. Es enthält dann &lt;br /&gt;
meist mehrere Tausend Dateien, auch wenn das eigentliche Projekt nur aus ein paar wenigen Dateien besteht. Dies ist vor allem beim Speichern eines derartigen Projektes in eine Repository ([[SVN]], [[Git]] etc.)&lt;br /&gt;
sehr störend. Dennoch sollte man nur ein Paket wie &amp;lt;code&amp;gt;grunt-cli&amp;lt;/code&amp;gt;, dessen einzige Aufgabe es ist, die jeweils projektlokale Version von Grunt auszuführen, global installieren.&lt;br /&gt;
&lt;br /&gt;
Um das Repository-Problem zu vermeiden, muss man die Speicherung von Node.js-Bibliotheken im Repository ausschließen und&lt;br /&gt;
diese Dateien bei Bedarf automatisch von den entsprechenden Servern herunterladen. Wie das geht, haben wir gerade gesehen:&lt;br /&gt;
Man läd das Projekt auf seinen Arbeitsrechner, öffnet ein Terminal, wechselt mittels &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt; ins Wurzelverzeichnis des Projektes &lt;br /&gt;
(beim WebStorm-Terminal befindet man sich standardmäßig immer im Root-Verzeichnis des Projektes) und führt&lt;br /&gt;
&amp;lt;code&amp;gt;npm install&amp;lt;/code&amp;gt; aus. &lt;br /&gt;
&lt;br /&gt;
===Grunt===&lt;br /&gt;
&lt;br /&gt;
Als nächstes initialisieren Sie Grunt (https://gruntjs.com/) &amp;lt;ref&amp;gt;Grunt: https://gruntjs.com/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Grunt ist ein “JavaScript Task Runner”, also ein Programm, das Aufgaben (&#039;&#039;tasks&#039;&#039;) wie {{zB}} das Übersetzen von [[ECMAScript|ECMAScript 2015/16/17]] in &lt;br /&gt;
ECMAScript 5.1 oder das Komprimieren von Programmdateien automatisch durchführt. &lt;br /&gt;
&lt;br /&gt;
Die Initialisierung erfolgt durch die Bereitstellung zweier Dateien &amp;lt;code&amp;gt;package.json&amp;lt;/code&amp;gt;&lt;br /&gt;
und &amp;lt;code&amp;gt;gruntfile.json&amp;lt;/code&amp;gt; im Root-Verzeichnis der Web-Anwendung. Die Datei &amp;lt;code&amp;gt;package.json&amp;lt;/code&amp;gt;&lt;br /&gt;
haben Sie schon mittels &amp;lt;code&amp;gt;npm init&amp;lt;/code&amp;gt; erstellt.&lt;br /&gt;
&lt;br /&gt;
In der Datei &amp;lt;code&amp;gt;package.json&amp;lt;/code&amp;gt; gibt es das Attribut &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;.&lt;br /&gt;
Es enthält den Namen der Konfigurationsdatei von Grunt: &amp;lt;code&amp;gt;gruntfile.js&amp;lt;/code&amp;gt;. &lt;br /&gt;
Diese fehlt allerdings noch. Also legen Sie sie im Wurzelverzeichnis des Projektes mit einem Texteditor Ihrer Wahl an&lt;br /&gt;
(WebStorm: &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;WebStorm&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;New&amp;lt;/code&amp;gt;  → &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;gruntfile.js&amp;lt;/code&amp;gt;&#039;&#039;&#039; &lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
module.exports = function(grunt)&lt;br /&gt;
{&lt;br /&gt;
  // Project configuration.&lt;br /&gt;
  grunt.initConfig&lt;br /&gt;
  ({&lt;br /&gt;
    pkg: grunt.file.readJSON(&#039;package.json&#039;),&lt;br /&gt;
  });&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei ist noch ziemlich leer, aber das wird sich ändern.&lt;br /&gt;
&lt;br /&gt;
Vorausschauend sollten Sie eine überflüssige WebStorm-Fehlerprüfung deaktivieren, da anderenfalls künftige&lt;br /&gt;
Änderungen an der Datei &amp;lt;code&amp;gt;gruntfile.js&amp;lt;/code&amp;gt; jedes Mal eine Fehlermeldung zur Folge haben, wenn die&lt;br /&gt;
Datei in ein SVN-Repository geschrieben werden soll:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;WebStorm&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Settings&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;Preferences&amp;lt;/code&amp;gt;  → &amp;lt;code&amp;gt;Editor&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Inspections&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaScript&amp;lt;/code&amp;gt; aufklappen → &amp;lt;code&amp;gt;General&amp;lt;/code&amp;gt; aufklappen → &amp;lt;code&amp;gt;Unused global symbols&amp;lt;/code&amp;gt; deselektieren&lt;br /&gt;
* &amp;lt;code&amp;gt;OK&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Babel===&lt;br /&gt;
&lt;br /&gt;
Das Compiler „Babel“&amp;lt;ref&amp;gt;Babel: https://babeljs.io/&amp;lt;/ref&amp;gt; wurde geschaffen, da die meisten Browser zwar ECMAScript 5.1&lt;br /&gt;
unterstützten&amp;lt;ref&amp;gt;ECMAScript 5 compatibility table: https://kangax.github.io/compat-table/es5/&amp;lt;/ref&amp;gt;, &lt;br /&gt;
aber nicht die Nachfolgesprachen  ECMAScript 2015, ECMAScript 2016 und ECMAScript 2017.&lt;br /&gt;
Dies hat sich in jüngster Zeit deutlich gebessert. Die meisten Browser unterstützen diese Sprachen in der Zwischenzeit&lt;br /&gt;
sogar besser als Babel.&amp;lt;ref&amp;gt;ECMAScript 6 compatibility table: https://kangax.github.io/compat-table/es6/&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;ECMAScript 2016+ compatibility table: http://kangax.github.io/compat-table/es2016plus/&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Allerdings verstehen die meisten Browser derzeit die sehr wichtigen Export- und Import-Befehle noch nicht.&amp;lt;ref&amp;gt;Export-Statement: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/export&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Import-Statement: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/import&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In solchen Fällen kommt Babel zum Einsatz. Babel übersetzt moderneren ECMAScript-Code in älteren ECMAScript-Code. &lt;br /&gt;
(Da „Babel“ den Code nicht in eine  maschinennähere Sprache sondern nur in eine alternative ECMAScript-Version übersetzt, &lt;br /&gt;
sagen viele Nutzer „Transpiler“ an Stelle von „Compiler“.) Auf diese Weise wird erreicht, dass eine deutlich größere Anzahl von Browsern&lt;br /&gt;
den Code ausführen kann. &lt;br /&gt;
&lt;br /&gt;
Babel wurde selbst in ECMAScript geschrieben und liegt  in Form von Node.js-Paketen vor.&amp;lt;ref&amp;gt;babel-cli: https://www.npmjs.com/package/babel-cli&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;babel-preset-env: https://github.com/babel/babel-preset-env&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;grunt-babel: https://github.com/babel/grunt-babel&amp;lt;/ref&amp;gt; &lt;br /&gt;
Installieren Sie diese zunächst:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm install --save-dev grunt babel-cli babel-preset-env grunt-babel&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun muss Babel noch konfiguriert werden. Theoretisch könnten Sie den Übersetzer einfach von der Kommandozeile aus&lt;br /&gt;
aufrufen (da ein Command Line Interface – CLI vorliegt). Aber das ist auf dauer etwas mühsam. Besser ist es&lt;br /&gt;
einen Grunt-Task zu definieren, der diese Aufgabe übernimmt.&lt;br /&gt;
&lt;br /&gt;
Andern Sie den Inhalt der Datei &amp;lt;code&amp;gt;gruntfile.js&amp;lt;/code&amp;gt;:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
module.exports = function(grunt)&lt;br /&gt;
{&lt;br /&gt;
  // Project configuration.&lt;br /&gt;
  grunt.initConfig&lt;br /&gt;
  ({&lt;br /&gt;
    pkg: grunt.file.readJSON(&#039;package.json&#039;),&lt;br /&gt;
&lt;br /&gt;
    babel:&lt;br /&gt;
    {&lt;br /&gt;
      options:&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;sourceMap&amp;quot;: true&lt;br /&gt;
      },&lt;br /&gt;
      dist:&lt;br /&gt;
      {&lt;br /&gt;
        files:&lt;br /&gt;
        [{&lt;br /&gt;
          &amp;quot;expand&amp;quot;: true,&lt;br /&gt;
          &amp;quot;cwd&amp;quot;:    &amp;quot;src/js&amp;quot;,&lt;br /&gt;
          &amp;quot;src&amp;quot;:    [&amp;quot;**/*.js&amp;quot;],&lt;br /&gt;
          &amp;quot;dest&amp;quot;:   &amp;quot;web/js/&amp;quot;,&lt;br /&gt;
          &amp;quot;ext&amp;quot;:    &amp;quot;.js&amp;quot;&lt;br /&gt;
        }]&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
  // Register task(s)&lt;br /&gt;
  grunt.loadNpmTasks(&amp;quot;grunt-babel&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  // Default task(s).&lt;br /&gt;
  grunt.registerTask(&amp;quot;default&amp;quot;, [&amp;quot;babel&amp;quot;]);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Babel-Konfiguration bewirkt, dass alle Dateien mit der Endung &amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;, die sich&lt;br /&gt;
vom Projekt-Wurzelverzeichnis &amp;lt;code&amp;gt;&amp;amp;lt;ROOT&amp;amp;gt;&amp;lt;/code&amp;gt; aus gesehen im Ordner &amp;lt;code&amp;gt;src/js&amp;lt;/code&amp;gt; oder einem darin enthaltenen Unterordner befinden,&lt;br /&gt;
mit Hilfe von Babel übersetzt und in den Ordner  &amp;lt;code&amp;gt;&amp;amp;lt;ROOT&amp;amp;gt;/web/js&amp;lt;/code&amp;gt; kopiert werden. Dort erhalten sie ebenfalls die Endung &amp;lt;code&amp;gt;.js&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;Grunt – Building the files object dynamically: https://gruntjs.com/configuring-tasks#building-the-files-object-dynamically&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe des Befehle &amp;lt;code&amp;gt;grunt.loadNpmTasks(&amp;quot;grunt-babel&amp;quot;);&amp;lt;/code&amp;gt; wird &lt;br /&gt;
der Task registriert. Er kann ab sofort im Wurzelverzeichnis des Projektes mit dem &lt;br /&gt;
Befehl &amp;lt;code&amp;gt;grunt babel&amp;lt;/code&amp;gt; aktiviert werden. Der Befehl&lt;br /&gt;
&amp;lt;code&amp;gt;grunt.loadNpmTasks(&amp;quot;grunt-babel&amp;quot;);&amp;lt;/code&amp;gt; sorgt dafür, dass &lt;br /&gt;
der Task &amp;lt;code&amp;gt;babel&amp;lt;/code&amp;gt; zur Liste der Default-Aktionen von Grunt hinzugefügt wird.&lt;br /&gt;
Das heißt, wenn man &amp;lt;code&amp;gt;grunt&amp;lt;/code&amp;gt; ohne Argument aufruft, wird der&lt;br /&gt;
Babel-Task ebenfalls ausgeführt.&amp;lt;ref&amp;gt;Grunt API: https://gruntjs.com/api/grunt&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um Babel zu testen erzeugen Sie die Datei &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt;:&lt;br /&gt;
* &amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;WebStorm&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;New&amp;lt;/code&amp;gt;  → &amp;lt;code&amp;gt;Directory&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;File&amp;lt;/code&amp;gt;&lt;br /&gt;
Fügen Sie folgenden EcmaScript-6-Code ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
let evens = [0, 2, 4, 6, 8],&lt;br /&gt;
    odds  = evens.map(langer_parameter_name =&amp;gt; langer_parameter_name + 1),&lt;br /&gt;
    pairs = evens.map(v =&amp;gt; ({ even: v, odd: v + 1 }));&lt;br /&gt;
&lt;br /&gt;
let name = &amp;quot;Anna&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
console.log(evens);&lt;br /&gt;
console.log(odds);&lt;br /&gt;
console.log(pairs);&lt;br /&gt;
console.log(`Hello ${name}!`);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei können Sie in WebStorm direkt ausführen:&lt;br /&gt;
* Im Dateibaum Rechtsklick auf &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Run &#039;main.js&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Ergebnis sehen Sie im Konsolfester von WebStorm, da Node.js schon zu 99% ECMAScript-2015-kompatibel ist.&amp;lt;ref&amp;gt;Node.js ES2015 Support: http://node.green/&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nun können Sie die Datei &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt; mit Hilfe von Babel übersetzen.&lt;br /&gt;
Rufen Sie einfach einmal im Terminal einen der beiden Befehle &amp;lt;code&amp;gt;grunt babel&amp;lt;/code&amp;gt; oder einfach nur &amp;lt;code&amp;gt;grunt&amp;lt;/code&amp;gt;  im&lt;br /&gt;
Wurzelverzeichnis des Projektes auf. Sie werden anschließend feststellen, dass ein Ordner &lt;br /&gt;
&amp;lt;code&amp;gt;web/js&amp;lt;/code&amp;gt; angelegt und in diesen eine Datei namens &amp;lt;code&amp;gt;main.js&amp;lt;/code&amp;gt;&lt;br /&gt;
eingefügt wurde. Wenn Sie sich den Inhalt dieser Datei ansehen, stellen Sie fest,&lt;br /&gt;
dass sich sich nicht von der Datei &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt; unterscheidet. &lt;br /&gt;
&lt;br /&gt;
Das ist nicht weiter verwunderlich, das Babel default-mäßig gar keine Veränderungen vornimmt.&lt;br /&gt;
Sie können sehr feingranular bestimmen, welche Übersetzungen stattfinden sollen.&lt;br /&gt;
Erstellen Sie im Wurzelbezeichnis des Projektes die Datei &amp;lt;code&amp;gt;.babelrc&amp;lt;/code&amp;gt;&lt;br /&gt;
und fügen Sie folgenden Code ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;presets&amp;quot;: [&amp;quot;env&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Wenn Sie jetzt den Befehl &amp;lt;code&amp;gt;grunt&amp;lt;/code&amp;gt; noch einmal ausführen, werden Sie feststellen,&lt;br /&gt;
dass sich &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;web/js/main.js&amp;lt;/code&amp;gt; deutlich unterscheiden.&lt;br /&gt;
Die Datei &amp;lt;code&amp;gt;web/js/main.js&amp;lt;/code&amp;gt; enthält nun astreinen ECMAScript-5-Code. Diesen können Sie&lt;br /&gt;
in WebStorm natürlich auch problemlos ausführen. Und in der Konsole werden dieselben Informationen &lt;br /&gt;
ausgegeben wie zuvor von &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Babel kann den erzeugten Code auch noch gleich komprimieren, das heißt, überflüssige &lt;br /&gt;
Kommentare, Leerzeichen und Zeilenumbrüche entfernen, lange Variablen-, Funktions- und Parameternamen&lt;br /&gt;
durch kurze ersetzen, wann immer dies möglich ist, etc. Dafür benötigt man die &lt;br /&gt;
Node.js-Pakete &amp;lt;code&amp;gt;babel-minify&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;babel-preset-minify&amp;lt;/code&amp;gt;.&amp;lt;ref&amp;gt;babel-minify: https://github.com/babel/minify&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;babel-preset-minify: https://www.npmjs.com/package/babel-preset-minify&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm install --save-dev babel-minify babel-preset-minify&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn Sie nun den Inhalt der Datei &amp;lt;code&amp;gt;.babelrc&amp;lt;/code&amp;gt; durch Folgenden Code ersetzen,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;presets&amp;quot;: [&amp;quot;env&amp;quot;, &amp;quot;minify&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
wird &amp;lt;code&amp;gt;main.js&amp;lt;/code&amp;gt;mittels &amp;lt;code&amp;gt;grunt babel&amp;lt;/code&amp;gt; nicht nur in ECMAScript 5 übersetzt, sondern auch noch komprimiert.&lt;br /&gt;
&lt;br /&gt;
Wird dagegen &lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;presets&amp;quot;: [&amp;quot;minify&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
geschrieben, wird die Datei nur komprimiert, der ECMAScript-2015-Code bleibt hingegen erhalten.&lt;br /&gt;
&lt;br /&gt;
===Automatische Dateierzeugung mittels Grunt===&lt;br /&gt;
&lt;br /&gt;
Einen Nachteil hat die Lösung mit der Übersetzung von Dateien noch.&lt;br /&gt;
Jedesmal wenn man eine Änderung an &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt; vornimmt, muss man&lt;br /&gt;
den Befehl &amp;lt;code&amp;gt;grunt&amp;lt;/code&amp;gt; aufrufen, um &amp;lt;code&amp;gt;web/js/main.js&amp;lt;/code&amp;gt; zu erzeugen.&lt;br /&gt;
Das ist lästig und fehleranfällig. Besser ist es, bei jeder Änderung der Datei &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt;&lt;br /&gt;
die Datei &amp;lt;code&amp;gt;web/js/main.js&amp;lt;/code&amp;gt; automatisch zu erstellen. Dies geht mit Hilfe des Node.js-Pakets&lt;br /&gt;
&amp;lt;code&amp;gt;grunt-contrib-watch&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;grunt-contrib-watch: https://github.com/gruntjs/grunt-contrib-watch&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
npm install --save-dev grunt-contrib-watch&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fügen Sie nun in die Datei &amp;lt;code&amp;gt;gruntfile.js&amp;lt;/code&amp;gt; hinter &lt;br /&gt;
dem &amp;lt;code&amp;gt;babel&amp;lt;/code&amp;gt;-Block folgenden&lt;br /&gt;
Block ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
 watch:&lt;br /&gt;
 { &lt;br /&gt;
   js:&lt;br /&gt;
   { files:   [&#039;src/js/**/*.js&#039;],&lt;br /&gt;
     tasks:   [&#039;babel&#039;]&lt;br /&gt;
   }&lt;br /&gt;
 },&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend müssen Sie den Watch-Task in derselben Datei noch mittels&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
grunt.loadNpmTasks(&#039;grunt-contrib-watch&#039;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
registrieren. Das war es schon. Wenn Sie jetzt den Watch-Task mittels&lt;br /&gt;
&amp;lt;code&amp;gt;grunt watch&amp;lt;/code&amp;gt; in einer Konsole im Wurzelverzeichnis des Projekts starten,&lt;br /&gt;
wird jedesmal, wenn Sie eine Änderung an der Datei &amp;lt;code&amp;gt;src/js/main.js&amp;lt;/code&amp;gt;&lt;br /&gt;
vornehmen und diese speichern, wird die Datei &amp;lt;code&amp;gt;web/js/main.js&amp;lt;/code&amp;gt; automatisch erstellt.&lt;br /&gt;
Versuchen Sie es.&lt;br /&gt;
&lt;br /&gt;
Sie können noch diverse weitere Grunt-Tasks automatisch ausführen lassen,&lt;br /&gt;
wenn Sie sie in die Watch-Liste eintragen. Solange der  Watch-Task läuft, brauchen &lt;br /&gt;
Sie also nichts weiter zu tun, als Ihre Sourcen zu bearbeiten und die erzeugten&lt;br /&gt;
Dateien ({{iAllg}} im Browser) zu testen. Sie können den Watch-Task jederzeit&lt;br /&gt;
beenden um andere Befehle im WebStorm-Terminal auszuführen.&lt;br /&gt;
Sie können aber auch ein zweites Terminal öffnen ({{zB}} eine Git-Bash) und diesen&lt;br /&gt;
Prozess dauerhaft laufen lassen, solange Sie an Ihrem Projekt arbeiten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
npm install --save-dev babel-plugin-transform-es2015-modules-commonjs&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==Quellen==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li value=&amp;quot;18&amp;quot;&amp;gt; {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
[[Kategorie: HTML5-Tutorium: JavaScript: Entwicklungsumgebung]]&lt;br /&gt;
[[Kategorie: HTML5-Beispiel]]&lt;br /&gt;
[[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]&lt;br /&gt;
[[Kategorie:Praktikum:MMProg]]&lt;/div&gt;</summary>
		<author><name>Jostl</name></author>
	</entry>
</feed>