HTML5-Tutorium: JavaScript: Hello World 06: Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Kowa (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
Kowa (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
 
(84 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
{{In Bearbeitung}}
{{HTML5-Tutorium:JavaScript:HelloWorld:Menü}}
{{HTML5-Tutorium:JavaScript:HelloWorld:Menü}}


'''Musterlösung''': [https://glossar.hs-augsburg.de/beispiel/tutorium/es5/hello_world/WK_HelloWorld05/web/index.html <code>index.html</code>],
'''Musterlösung'''<br/>
[([https://glossar.hs-augsburg.de/beispiel/tutorium/es6/hello_world/WK_HelloWorld05/ SVN-Repository])
[https://glossar.hs-augsburg.de/beispiel/tutorium/2025/wk_hello_world/wk_hello_world_06/web/index.html <code>index.html</code>] ([https://validator.nu/?doc=https%3A%2F%2Fglossar.hs-augsburg.de%2Fbeispiel%2Ftutorium%2F2025%2Fwk_hello_world%2Fwk_hello_world_06%2Fweb%2Findex.html HTML validate], [https://css-validator.org/validator?uri=https%3A%2F%2Fglossar.hs-augsburg.de%2Fbeispiel%2Ftutorium%2F2025%2Fwk_hello_world%2Fwk_hello_world_06%2Fweb%2Findex.html&profile=css21&usermedium=all&warning=1&lang=de CSS validate], [https://pagespeed.web.dev/analysis?url=https%3A%2F%2Fglossar.hs-augsburg.de%2Fbeispiel%2Ftutorium%2F2025%2Fwk_hello_world%2Fwk_hello_world_06%2Fweb%2Findex.html Google PageSpeed])<br/>
==Anwendungsfälle (Use Cases)==
[{{Git-Server}}/kowa/wk_hello_world_06.git Git-Repository]
Gegenüber dem [[HTML5-Tutorium:_JavaScript:_Hello_World_04|vierten Teil des Tutoriums]]
ändern sich die die Anwendungsfälle nur geringfügig. Das Begrüßungsformular soll ''zweimal''
im Browser angezeigt werden, einmal auf Deutsch und auf Englisch. Beide Begrüßungsformulare sollen
unabhängig voneinander funktionieren.


Ein Grundprinzip der Programmierung lautet [[Don't repeat yourself]] (DRY).  Sie könnten nun einfach den vorhandenen
== Anwendungsfälle (Use Cases) ==
Code duplizieren und entsprechend anpassen. Aber genau das würde gegen das Prinzip „Keep your code DRY“ verstoßen.
Gegenüber dem [[HTML5-Tutorium:_JavaScript:_Hello_World_05|dritten, vierten und fünften Teil des Tutoriums]]
Code-Duplikation kann mit Hilfe von [[Klasse (objektorientiert)|Klassen]] vermieden werden. Sie stellen eine Art
ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.
„Blaupause“ dar, um Objekte mit ähnlichen Eigenschaften ganz einfach erstellen zu können.


==Erstellen eines neuen Projektes==
In diesem Teil des Tutoriums geht es darum, den CSS-Code „[[DRY]] zu machen“.


Erzeugen Sie wie im  [[HTML5-Tutorium:_JavaScript:_Hello_World_04|vierten Teil des Tutoriums]] ein neues Projekt,
== Erstellen eines neuen Projekts ==
diesmal allerdings mit dem schönen Namen <code>HelloWorld05</code>“ und speichern Sie dieses wieder
in Ihrem SVN-Repository (Achtung: <code>node_modules</code> muss existieren und auf der Ignore-Liste stehen). 


Kopieren Sie nun aus Ihrer Lösung des vierten Teil des Tutoriums die Ordner <code>src</code> und <code>web</code>
Erstellen Sie ein neues Projekt <code>hello_world_06</code> als Fork von <code>hello_world_05</code>.
(jeweils samt allen darin enthaltenen Ordnern und Dateien) sowie die Dateien <code>gruntfile.js</code>,
<code>package.json</code>, <code>package-lock.json</code> und <code>webpack.config.js</code>
fügen Sie sie ins Wurzelverzeichnis des fünften Teils ein.  


Weisen Sie WebStorm wiederum an, die Inhalte der Ordner <code>node_modules</code> und <code>web/js</code>
== CSS-Erweiterungen ==
nicht auf Syntaxfehler zu überprüfen. Gegebenenfalls müssen Sie auch wieder die Dateien <code>gruntfile.js</code>
... <code>webpack.config.js</code> unter die Versionsverwaltung von SVN stellen (<code>Add to VCS</code>).


Ändern Sie in den Dateien <code>package.json</code> und <code>web/index.html</code> die Versionsnummern,
CSS bietet heute dieselbe Funktionalität wie Transpiler ([[SASS]], [[Less]] etc.), die früher verwendet wurden, um fehlende Funktionalität in CSS zu integrieren. Ich werde in diesem Semester CSS an Stelle von SCSS einsetzen, so wie es von vite empfohlen wird:
die Beschreibung und gegebenenfalls den Pfad zum Repository Ihres Projektes.


Zu guter Letzt öffnen Sie das WebStorm-Terminal und führen den Befehl <code>npm install</code>aus.
''Because Vite targets modern browsers only, it is recommended to use native CSS variables with PostCSS plugins that implement CSSWG drafts (e.g. postcss-nesting) and author plain, future-standards-compliant CSS.'' (https://vite.dev/guide/features)
Damit werden dieselben Node.js-Pakete installiert wie im vierten Teil des Tutoriums.


Löschen Sie die Datei <code>web/js/app.bundle.js</code> und
Eine ganz wesentliche Erweiterung ist die Möglichkeit Konstanten zu definieren.
rufen Sie anschließend <code>grunt</code> auf, um diese Datei erneut zu erzeugen.
Auch die Möglichkeit, Werte zu berechnen, gibt es in der Zwischenzeit (SCSS: <code>math</code>, CSS: <code>calc</code>). Es ist jetzt auch möglich CSS-Elemente zu verschachteln.  
Wenn Sie jetzt die Datei <code>index.html</code> im Browser öffnen, sollte die
Das heißt, die Bedeutung von SCSS, Less etc. schwindet.
Web-Anwendung so wie in Teil 4 der Aufgabe funktionieren.


==Verfeinerung der Webpack-Umgebung==
== CSS-Konstanten ==
Zunächst benötigen Sie ein paar weitere Node.js-Module
<source lang="bash">
npm install --save-dev es6-autobind
npm install --save-dev node-sass sass-loader
npm install --save-dev extract-text-webpack-plugin optimize-css-assets-webpack-plugin
</source>


Das Modul <code>es6-autobind</code> wird im Zusammenhang mit der Definition der Klasse <code>Greet</code>
Eine ganz wesentliche Erweiterung ist die Möglichkeit Konstanten zu definieren, da man damit CSS-Code [[DRY]] formulieren kann.  
benötigt . Daher wird es erst später besprochen.


Im vierten Teil des Tutoriums wurde die Datei <code>initial.css</code> nicht von Webpack verwaltet,
Wenn eine Konstante definiert wurde, kann man
sondern direkt in das Verzeichnis <code>web/css</code> eingefügt. Damit liegt auch die
im übrigen CSS-Code mittels <code>var</code> darauf zugreifen (und nicht etwa mittels <code>const</code>, :-( )
Verantwortung für die Komprimierung dieser Datei beim Programmierer. Das soll sich ändern.
Sie erweitern die Webpack-Konfiguration so, dass künftig auch diese Datei unter der Kontrolle
von Webpack steht.


===SCSS===
<syntaxhighlight lang="CSS">
:root
{ --font-family-serif: "Times New Roman", Times, serif; }


Anstelle von CSS-Dateien verwenden Sie künftig SCSS-Dateien. Das ist zunächst einmal nicht weiter schwer,
p
das jede CSS-Datei automatisch auch eine SCSS-Datei ist. Bei der Verwendung von CSS können Sie
{ font-family: var(--font-family-serif); }
allerdings das Prinzip  „[[Don't repeat yourself]]“ (DRY) nicht beachten. Sie müssen für verschiedene Elemente
ständig Informationen wiederholen (gewünschter Font, Hintergrundfarbe, Größenangaben etc.). Deshalb
gibt es mehrere Projekte wie {{zB}} [[LESS]] und [[Sass]] , die den CSS-Standard erweitern, um dieses Problem
zu vermeiden. Sass verwendet allerdings eine ganz andere Syntax als CSS. Allerdings
unterstützt das Sass-Projekt auch die Sprache SCSS, die CSS einfach um weitere syntaktische Elemente ergänzt.
Zum Beispiel kann man in SCSS Konstanten definieren:


<source lang="CSS">
label
$background-color:  #C5EFFC;
{ font-family: var(--font-family-serif); }
</source>
</syntaxhighlight>
 
Auch die Möglichkeit, Werte zu berechnen, gibt es in der Zwischenzeit (SCSS: <code>math</code>, CSS: <code>calc</code>).
Das heißt, die Bedeutung von SCSS, Less etc. schwindet. In diesem Semester verwende ich nicht mehr SCSS, sondern nur noch CSS.
 
Fügen Sie <code>"config"</code> als Abkürzung für <code>"./src/css/_config.css"</code> in die Datei <code>vite.config.js</code> ein.


Und nun kann man in der CSS-Datei anstelle von  <code>#C5EFFC</code> stets  <code>&#36;background-color</code>
<syntaxhighlight lang="javascript">
schreiben, um die Hintergrundfarbe von bestimmten Elementen zu definieren. Wenn man nun dieses Farbe ändern will,
...
muss das nicht mehr bei allen Elementen einzeln passieren. Es reicht, die Farbe in der Konstantendefinition abzuändern.
  resolve:
Der CSS-Code ist nun DRY.
  { alias:
    { ...
      'config.css': fileURLToPath(new URL('./src/css/_config.css', import.meta.url)),
      ...
    }
  }
...
</syntaxhighlight>


Leider unterstützt kein Browser SCSS direkt. Aber für was gibt es Transpiler wie Webpack, die eine SCSS-Datei
In der Datei <code>_config.css</code> werden Konstanten definiert, die von allen anderen CSS-Dateien verwendet werden können und sollen.
automatisch in eine CSS-Datei übersetzen können.


Ersetzen Sie in Ihrem Projekt die Datei <code>src/css/main.css</code> durch
Das heißt, das DRY-Prinzip „Konstanten gehören nicht in den Code, sondern in Konfigurationsdateien“ wird ab sofort beachtet.
drei SCSS-Dateien: <code>_config,scss</code>, <code>initial.scss</code> und </code>app.scss</code>.


In der Datei <code>_config,scss</code> werden alle von den anderen SCSS-Dateien benötigten Konstanten definiert.
Wenn man künftig am Layout einen Zeichensatz, eine Farbe, einen Hintergrund oder Ähnliches ändern will,  
Wenn man künftig am Layout einen Zeichensatz, eine Farbe, einen Hintergrund oder Ähnliches ändern will,  
reicht es die entsprechenden Konstanten anzupassen und schon erzeugt Webpack automatisch aktualisiere
reicht es, die entsprechenden Konstanten anzupassen und schon erzeugt Vite automatisch aktualisiere
CSS-Dateien.
CSS-Dateien.


Die Datei <code>initial.scss</code> enthält möglichst wenig Code. Das ist Vorlage für die Datei <code>initial.bundle.css</code>,  
Durch den CSS-Import-Befehl ist es möglich, CSS-Dateien zu modularisieren.
die im HTML-Head-Bereich geladen vor dem Body-Inhalt werden soll.
Der Underscore <code>_</code> am Beginn des Dateinamens deutet an, dass diese CSS-Datei nur von anderen CSS-Dateien
Die eigentlichen CSS-Informationen der Web-Anwendung werden in <code>app.scss</code> gespeichert. Die zugehörigen
aber nicht von HTML- oder JavaScript-Dateien importiert werden sollte.
CSS-Anweisungen werden von Webpack wie gehabt in <code>app.bundle.js</code> integriert.
 
'''<code>src/css/_config.css</code>'''
<syntaxhighlight lang="CSS">
:root
{ --background-color:  #C5EFFC;
 
  --font-family-sans:  Verdana, Helvetica, sans-serif;
  --font-family-serif: "Times New Roman", Times, serif;
 
  --font-size-base:    3vw;
  --font-size-factor:  1.25;  /* cmp. https://type-scale.com/ */
 
  --font-size-h5:      calc(pow(var(--font-size-factor),1)*var(--font-size-base));
  --font-size-h4:      calc(pow(var(--font-size-factor),2)*var(--font-size-base));
  --font-size-h3:      calc(pow(var(--font-size-factor),3)*var(--font-size-base));
  --font-size-h2:      calc(pow(var(--font-size-factor),4)*var(--font-size-base));
  --font-size-h1:      calc(pow(var(--font-size-factor),5)*var(--font-size-base));
 
  --font-size-p:      calc(pow(var(--font-size-factor),0)*var(--font-size-base));
  --font-size-p-large: calc(pow(var(--font-size-factor),2)*var(--font-size-base));
 
  --font-size-small:  calc(pow(var(--font-size-factor),-1)*var(--font-size-base));
}
</syntaxhighlight>
In dieser CSS-Datei werden folgende modernen CSS-Konstrukte verwendet:
 
* Definition von Konstanten (die teilweise per Berechnung ermittelt werden)
* Mathematische Berechnungen: <code>calc</code>
 
Konstanten starten in CSS mit zwei Minuszeichen. Sobald eine Konstante definiert wurde,
kann sie in allen weiteren CSS-Konstrukten verwendet werden. In CSS stehen einen Operatoren zur Verfügung wie
<code>+</code>, <code>-</code>, <code>*</code> und <code>/</code>, um Maße zu berechnen. Es gibt
weitere Operatoren zum Vergleichen von Zahlen und Maßen sowie zur Berechnung von Strings und booleschen Werten:
https://sass-lang.com/documentation/operators.<ref>https://sass-lang.com/documentation/operators</ref>
 
Die Datei <code>_config.css</code> kann nun mit Hilfe des CSS-Befehls <code>@import 'config.css';</code> (ohne Underscore und ohne <code>.css</code>, wegen des zuvor eingeführten Vite-Aliases)
in die anderen beiden CSS-Dateien eingefügt werden.
 
=== PostCSS ===
 
Der Inhalt der Datei <code>_config.css</code> wird defaultmäßig an den Browser ausgeliefert, obwohl sie nur CSS-Konstanten enthält.
Beim Einsatz vom SCSS werden Konstanten vom SCSS-Präprozessor auf dem Server während des Build-Prozesses durch ihre Werte ersetzt.  
In CSS muss dies defaultmäßig der Browser übernehmen. Es gibt allerdings ein PostCSS-Plugin [https://www.npmjs.com/package/postcss-var-replace/v/1.0.0 postcss-var-replace], das diese Ersetzungen ebenfalls während des Build-Prozesses vornimmt. Dieses kann man in die Vite-Konfiguration integrieren:
 
Laden sie das Pluging <code>postcss-var-replace</code>:


'''<code>src/css/_config,scss</code>'''
<syntaxhighlight lang="bash">
<source lang="CSS">
npm i -D postcss-var-replace
$font-family-sans:  Verdana, Helvetica, sans-serif;
</syntaxhighlight>
$font-family-serif: "Times New Roman", Times, serif;
$background-color:  #C5EFFC;
</source>


Diese Datei kann nun mit Hilfe des SCSS-Befehls <code>@import</code>  
Anschließend aktivieren Sie es in <code>vite.config.js</code>
in die anderen beiden  SCSS-Dateien eingefügt werden. Webpack (genauer gesagt das SASS-Modul von Webpack)
kennt diesen Befehl und führt im beim Erstellen der zugehörigen CSS-Dateien auch aus.


Der Import-Befehl ist hier notwendig, da in der Datei <code>initial.scss</code> die Konstante <code>&#36;background-color</code>
<syntaxhighlight lang="javascript">
verwendet wird. Ansonsten enthält dies Datei nur den schon bekannten CSS-Code.
import { postcssVarReplace }  from 'postcss-var-replace';


'''<code>src/css/initial.scss</code>'''
...
<source lang="CSS">
@import 'config';


body
export default
{ background-color: $background-color;
{ ...
  css:
  { postcss:
    { plugins:  
      [ postcssVarReplace(),
      ],
    },
  },
  ...
}
}
</syntaxhighlight>


Der Import-Befehl hat ab sofort erst dann einen Effekt, wenn in den anderen Dateien auf diese Konstanten zugegriffen wird.
Aber er schadet auch nicht, wenn auf keine der dort definierten Konstanten zugegriffen wird. Der Import-Befehl selbst
taucht ebenso wenig in den generierten CSS-Dateien auf, wie die Konstantendefinitionen. Der PostCSS-Transpiler ersetzt Konstanten in CSS-Definitionen durch ihren jeweiligen Wert.
Sie können nun beispielsweise in der Datei <code>head.css</code> die Konstante <code>--background-color</code>
verwenden. In dem daraus durch den Build-Befehl <code>npm run build</code> erzeugten CSS-Style-Element steht weiterhin der Farbwert <code>#C5EFFC</code>;
'''<code>src/css/head.css</code>'''
<syntaxhighlight lang="CSS">
@import 'config.css';
body
{ background-color: var(--background-color); }
.hidden
.hidden
{ display: none;
{ display: none; }
}
</syntaxhighlight>
</source>
 
Die Datei <code>app.scss</code> ist deutlich umfangreicher. Daher soll der zugehörige CSS-Code
ja auch erst gemeinsam mit der Datei  <code>app.bundle.js</code> geladen werden. Das meiste ist üblicher
CSS-Code, den Sie schon im vierten Teil des Tutoriums kennengelernt haben. Es gibt ein paar neue
Elemente, wie die CSS-Klassen-Elemente <code>.left</code> und <code>.right</code>, die in der HTML-Datei dieses
Tutoriums zusätzlich verwendet werden. Außerdem sehen Sie in der Datei noch ein  paar weitere SCSS-Elemente. Diese werden
im Anschluss an den folgenden code beschrieben.


'''<code>src/css/app.scss</code>'''
Die Datei <code>body.css</code> ist deutlich umfangreicher. Daher wird der zugehörige CSS-Code
<source lang="CSS">
ja auch erst dynamisch gemeinsam mit der Datei <code>web/js/main.js</code> geladen.
@import 'config';


html, body
'''<code>src/css/body.css</code>'''
{ height:          100%;
<syntaxhighlight lang="CSS">
  font-size:        2vw !important;
@import 'config.css';
  font-family:      $font-family-sans;
  background-color: $background-color;
}


html
html
{ display: table;
{ height: 100%;
   width:  100%;
   width:  100%;
  display: table;
}
}


Zeile 148: Zeile 176:
   text-align:      center;
   text-align:      center;
   vertical-align:  middle;
   vertical-align:  middle;
  font-size:        var(--font-size-base);
  font-family:      var(--font-family-sans);
}
}


h1
h1
{ padding-bottom: 0;
{ padding:   0;
   margin-bottom: 0;
   margin:   0;
}
  font-size: var(--font-size-h1);
 
#section_form
{ text-align:  center;
  width:       21em;
  margin-left:  auto;
  margin-right: auto;
 
  h1
  { font-size:    200%;
    margin-bottom: 0.5ex;
  }
}
 
#section_hello
{ h1
  { font-size: 270%;
  }
}
}


p, label
p, label
{ font-family: $font-family-serif;
{ font-family: var(--font-family-serif);
   font-size:  100%;
   font-size:  var(--font-size-p);
}
}


label, input, button
label, input
{ width:         10em;
{ width:     10em;
   font-size:     100%;
   font-size: 100%;
   display:       inline-block;
   display:   inline-block;
   box-sizing:   border-box;
   box-sizing: border-box;
   margin-bottom: 0.5ex;
   margin:     0.5ex;
}
}


Zeile 190: Zeile 203:
}
}


@mixin panel()
#section_form
{ padding: 0;
{ text-align:   center;
   width50%;
  margin-left:  auto;
   margin-right: auto;
 
  h1
   { margin-bottom: 0.5ex; }
}
}


.left
#section_hello
{ float: left;
{ p
   @include panel();
   { font-size: var(--font-size-p-large) !important; }
}
}
.right
</syntaxhighlight>
{ float: right;
  @include panel();
}
</source>


In diese SCSS-Datei werden folgende SCSS-Erweiterungen verwendet:
In dieser CSS-Datei werden folgende modernen CSS-Befehle verwendet:


* Import-Befehl: <code>@import 'config';</code>
* Import-Befehl: <code>@import 'config.css';</code>
* Konstanten:  <code>&#36;font-family-sans</code>, <code>&#36;font-family-serif</code>, <code>&#36;background-color</code>
* Konstanten:  <code>--font-family-sans</code>, <code>--font-size-base</code> etc. (Es sind noch viele weitere konstante Werte in <code>body.css</code> enthalten, für die in <code>_config.css</code> Konstanten definiert werden sollten)
* Verschachtelte Anweisungen: {{zB}} <code>h1</code> innerhalb von  <code>#section_form</code>
* Verschachtelte Anweisungen: {{zB}} <code>h1</code> innerhalb von  <code>#section_form</code>
* Mixins, um eine Liste von Attributen nur einmal zu definieren und und mehreren Elemente wieder verwenden zu können.


Die verschachtelten Anweisungen strukturieren den CSS-Code deutlich besser. Es ist nicht mehr
Die verschachtelten Anweisungen strukturieren den CSS-Code deutlich besser. Es ist nicht mehr
notwendig einen Selektor wie <code>#section_form</code> mehrfach zu verwenden.
notwendig, einen Selektor wie <code>#section_form</code> mehrfach zu verwenden.


Sehen Sie sich den Unterschied an. In der Datei <code>main.css</code> vom vierten Teil des Tutoriums hatten Sie
Sehen Sie sich den Unterschied an. In der Datei <code>src/css/body.css</code> der Musterlösungen vom dritten  Teil des Tutoriums hatte ich
folgendes geschrieben:
Folgendes geschrieben:


<source lang="CSS">
<syntaxhighlight lang="CSS">
#section_form
#section_form
{
{ text-align:  center;
  text-align:  center;
  width:        21em;
   margin-left:  auto;
   margin-left:  auto;
   margin-right: auto;
   margin-right: auto;
Zeile 228: Zeile 238:


#section_form > h1
#section_form > h1
{
{ margin-bottom: 0.5ex; }
  font-size:    200%;
</syntaxhighlight>
  margin-bottom: 0.5ex;
}
</source>


Die SCSS-Variante ist deutlich strukturierter und prägnanter.
Die modernen CSS-Variante ist deutlich strukturierter und prägnanter.


<source lang="CSS">
<syntaxhighlight lang="CSS">
#section_form
#section_form
{ text-align:  center;
{ text-align:  center;
  width:        21em;
   margin-left:  auto;
   margin-left:  auto;
   margin-right: auto;
   margin-right: auto;


   h1
   h1
   { font-size:    200%;
   { margin-bottom: 0.5ex; }
    margin-bottom: 0.5ex;
  }
}
}
</source>
</syntaxhighlight>


Insbesondere bei großen CSS-Dateien erweist sich diese kompaktere Schreibweise als vorteilhaft.
Insbesondere bei großen CSS-Dateien erweist sich diese kompaktere Schreibweise als vorteilhaft.


Ein weiteres Element, das nur SCSS bietet sind die Mixins. Sie definieren zunächst ein Mixin,
==Fortsetzung des Tutoriums==
das eine Folge von CSS-Attributen zusammenfasst. (Auch hier könnten wieder Verschachtelungen und
andere SCSS-Erweiterungen verwendet werden!)
 
<source lang="CSS">
@mixin panel()
{ padding: 0;
  width:  50%;
}
</source>
 
Und nun können Sie dieses Mixin in diversen andere Elemente einbinden:
 
<source lang="CSS">
.left
{ float: left;
  @include panel();
 
.right
{ float: right;
  @include panel();
}
</source>
 
In normalen CSS-Code, müssten Sie denselben Code Non-DRY formulieren:
 
<source lang="CSS">
.left
{ float:  left;
  padding: 0;
  width:  50%;
}
 
.right
{ float:  right;
  padding: 0;
  width:  50%;
}
</source>
 
Wenn Sie hier das Layout der Panels ändern wollten (andere Breite, andere Ränder etc.), müssen
Sie den CSS-Code von jedem Panel einzeln ändern. In der SCSS-Datei erfolgt die Änderung dagegen DRY: Sie ändern einfach den Mixin-Code ab. 
 
Wenn die aktuellen Browser SCSS verstehen würden, könnte sie <code>initial.scss</code> und <code>app.scss</code> direkt
vom HTML-Code aus laden. Allerdings geht das derzeit leider nicht. Somit muss Webpack angewiesen werden, CSS-Code aus den
SCSS-Dateien zu erzeugen. Dies ist mit den beiden Node.js-Modulen <code>node-sass</code> und <code>sass-loader</code>,
die Sie bereits installiert haben, ganz einfach möglich.
 
Ersetzen Sie in der Datei <code>webpack.config.js</code> folgenden Code
 
<source lang="javascript">
{ test:  /\.css$/,
  use:    [ 'style-loader',
            { loader: 'css-loader', options: { minimize: true } }
          ]
},
</source>
 
durch folgenden:
 
<source lang="javascript">
{ test:  /\.(css|scss|sass)$/,
  use:    [ 'style-loader',
            { loader: 'css-loader', options: { minimize: true } },
            'sass-loader'
          ]
}
</source>
 
Der Test wird so erweitert, dass diese Regel jetzt nicht nur für die Verarbeitung von Dateien mit der
Endung <code>.css</code> zuständig ist, sondern auch für Dateien mit den Endungen
<code>.sass</code> und <code>.scss</code>.
 
Die Liste der zugehörigen Loader wird einfach um einen Loader erweitert:  <code>sass-loader</code>.
Diese Liste wird von hinten nach vorne abgearbeitet. Das heißt, eine Datei wie beispielsweise <code>app.scss</code>
wird erst mit Hilfe des Sass-Loaders in eine CSS-Datei umgewandelt, diese wird mit Hilfe des CSS-Loaders komprimiert
und das Ergebnis dieser Datei wird mit Hilfe des Style-Loaders in die zugehörige JavaScript-Ausgabedatei integriert.
 
Jetzt müssen nur noch die zugehörigen JavaScript-Dateien erstellt werden.
 
Im <code>entry</code>-Objekt der Datei <code>webpack.config.js</code> ist bereits die Datei <code>src/js/app.js</code>
eingetragen. Für Sie wird von Webpack die Datei <code>web/js/app.bundle.js</code> erzeugt. (Der Name der Zieldatei
wurde im <code>output</code>-Objekt von <code>webpack.config.js</code> spezifiziert.)
 
Damit diese Zieldatei insbesondere den komprimierten Code der Datei <code>src/css/app.scss</code> enthält,
muss <code>src/js/app.js</code> leicht modifiziert werden.
 
Ersetzen Sie in dieser Datei den Import-Befehl
 
<source lang="javascript">
import '../css/main.css';
</source>
durch den Import-Befehl
 
<source lang="javascript">
import '../css/app.scss';
</source>
 
Die Datei <code>web/css/main.css</code> gibt es ja nicht mehr; sie wurde durch
<code>web/css/app.scss</code> ersetzt.
 
Damit auch <code>web/css/initial.scss</code> durch webpack verwaltet wird, benötigen wir eine zweite
JavaScript-Datei.
 
'''src/js/initial.js'''
<source lang="javascript">
import '../css/initial.scss';
</source>
 
Sie sehen das richtig, die Datei <code>src/js/initial.js</code> enthält eine einzige Code-Zeile.
Sie erinnern sich? Webpack dient eigentlich nur dazu JavaScript-Dateien zu packen. Also geben wir diesen
Tool eine JavaScript-Datei, die die gewünschte CSS-Datei einfach mittels eine ES6-Import-Befehls importiert (ES6 = EcmaScript 6).
Fügen Sie nun in das <code>entry</code>-Objekt der Datei <code>webpack.config.js</code> vor der Zeile
folgende zweite Zeile ein:
 
<source lang="javascript">
initial: absolutePath('src/js/initial.js')
</source>
 
Beachten Sie, dass in einem JavaScript-Objekt die Attribute durch Kommas voneinander getrennt werden. Fügen Sie also
an passender Stelle auch noch ein Komma ein.
 
Wenn Sie jetzt Grunt aufrufen, sollten zwei Dateien generiert werden: <code>web/js/app.bundle.js</code> und  <code>web/js/initial.bundle.js</code>.
 
Löschen Sie nun den Ordner <code>web/css</code> (die darin befindliche Datei <code>initial.css</code> wird nicht mehr benötigt)
und ersetzen Sie in der Datei <code>index.html</code> die Zeile
 
<source lang="html">
<link rel = "stylesheet" type = "text/css" href = "css/initial.css"/>
</source>
 
durch folgende Zeile:
 
<source lang="html">
<script type = "text/javascript" src = "js/initial.bundle.js"></script>
</source>
 
Wenn Sie jetzt die Datei <code>index.html</code> im Browser öffnen, sollte sie wieder genauso funktionieren wie zuvor.
 
'''Anmerkung''': Die Datei <code>src/js/initial.js</code> könnte natürlich noch mehr machen, als einfach nur eine CSS-Datei zu laden.
Sie könnte beispielsweise eine kleine Animation einblenden (die berühmte Sanduhr, nur etwas moderner), die solange läuft, bis
die eigentliche Web-Anwendung, {{dh}}  <code>app.bundle.js</code> vollständig geladen wurde und die Animation wieder beendet.
 
 
 
{{TBD}}
==Wiederverwendbarkeit==
<!--
Hinsichtlich der Wiederverwendbarkeit der Module ist die [[HTML5-Tutorium: JavaScript: Hello World 05|Version 4]]
noch relativ schlecht.
Allerdings gibt es noch ein paar Unsauberkeiten, die beseitigt werden sollten:
 
# In den Initialisierungsdateien  „<code>main3.js</code>“ und  „<code>main3b.js</code>“ sind immer noch konstante Werte enthalten.
# Die Anzahl der Parameter der Konstruktorfunktion ist zu groß.
# In den Initialisierungsdateien ist immer noch zu viel Anwendungscode enthalten.
# Die potentielle Zahl der globalen Größen ist noch zu hoch.
 
Diese Probleme werden folgendermaßen gelöst:
 
# Die Konstanten werden in eine [[JSON]]-Datei ausgelagert, die im ersten Schritt von der jeweiligen Initialisierungsdatei eingelesen wird.
# Der Konstruktorfunktion wird das gesamte JSON-Objekt mit allen Initialisierungswerten in einem einzigen Parameter übergeben.
# Es wird eine anwendungsspezifische Initialisierungsdatei „<code>hello.js</code>“ erstellt. Die Initialisierungsfunktion in der Datei „<code>main4.js</code>“ hat nur noch die Aufgabe, die JSON-Datei zu lesen und die darin enthalten Informationen anschließend an die Methode  „<code>hello.init</code>“ weiterzuleiten.
# Es wird '''ein''' globales Objekt namens  „<code>hello</code>“ erstellt, das die gesamte Web-Anwendung enthält.
 
Erstellen Sie in Ihrem WebStorm-Projekt Kopien Ihrer Anwendungsdateien:
 
* <code>index3b.html</code> → <code>index4.html</code>
* <code>js/main3b.js</code> → <code>js/main4.js</code>
* <code>js/app3/greet.js</code> → <code>js/app4/greet.js</code>
 
Im Folgenden wird die HTML-Datei „<code>index4.html</code>“
als HTML-[[Template]] verwendet, {{dh}} als Strukturrahmen. '''Sämtliche''' Texte,
die in diesem Dokument enthalten sind, werden dynamisch mittels JavaScript eingefügt.
 
In der Datei „<code>index4.html</code>“ müssen Sie also nicht nur dafür sorgen, dass
die neuen JavaScript-Dateien anstelle der alten geladen werden und dass der Titel angepasst wird.
Sie müssen auch sämtliche Text-Elemente mit eindeutigen ID-Attributen versehen.
 
Die HTML-Datei der Musterlösung sieht folgendermaßen aus. Sie können auch Ihre
eigene Datei verwenden, müssen dann aber die JSON-Datei, die anschließend erstellt wird,
entsprechend anpassen.
 
<source lang="javascript">
<!DOCTYPE html>
<html lang="en">
 
<head>
  <meta charset = "UTF-8">
  <meta name    = "viewport"
        content = "width=device-width, initial-scale=1.0, user-scalable=yes"
  >
 
  <title>WK_HelloWorld04 (4)</title>
 
  <link rel = "stylesheet" type = "text/css" href = "css/main.css"/>
</head>
 
<body>
  <div class="left">
    <section id="section1_form">
      <h1 id="heading1_form"></h1>
      <form>
        <div>
          <label id="label1_name" for="input1_name"></label>
          <input id="input1_name" type="text" autofocus="autofocus"/>
        </div>
        <div>
          <button id="button1_reset"  type="reset"></button>
          <button id="button1_submit" type="button"></button>
        </div>
      </form>
    </section>
    <section id="section1_hello" class="hidden">
      <h1 id="heading1_hello"></h1>
      <p id="paragraph1_hello"></p>
    </section>
  </div>
 
  <div class="right">
    <section id="section2_form">
      <h1 id="heading2_form"></h1>
      <form>
        <div>
          <label id="label2_name" for="input2_name"></label>
          <input id="input2_name" type="text" autofocus="autofocus"/>
        </div>
        <div>
          <button id="button2_reset"  type="reset"></button>
          <button id="button2_submit" type="button"></button>
        </div>
      </form>
    </section>
    <section id="section2_hello" class="hidden">
      <h1 id="heading2_hello"></h1>
      <p id="paragraph2_hello"></p>
    </section>
  </div>


  <script type = "text/javascript" src = "js/lib/wk/ajax.js"></script>
Sie sollten nun [[HTML5-Tutorium: JavaScript: Hello World Vue 01|Teil 1 des Vue-Tutoriums]] bearbeiten.
  <script type = "text/javascript" src = "js/app4/greet.js"></script>
In diesem Teil des Tutoriums wird die oben erstelle Variante in das Vue-Framework transferiert.
  <script type = "text/javascript" src = "js/app4/hello.js"></script>
  <script type = "text/javascript" src = "js/main4.js"></script>
</body>


</html>
</source>
-->
{{TBD}}
==Quellen==
==Quellen==
<references/>
<references/>
<ol>
<ol>
<li value="4"> {{Quelle|Kowarschick, W.: Multimedia-Programmierung}}</li>
<li value="5"> {{Quelle|Kowarschick, W.: Web-Programmierung}}</li>
</ol>
</ol>
<noinclude>[[Kategorie: HTML5-Tutorium: JavaScript: Hello World]][[Kategorie: HTML5-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]</noinclude>
<noinclude>[[Kategorie: HTML5-Tutorium: JavaScript: Hello World]][[Kategorie: HTML5-Beispiel]][[Kategorie:Kapitel:Multimedia-Programmierung:Beispiele]]</noinclude>

Aktuelle Version vom 11. April 2025, 09:25 Uhr

Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:

Korrektheit: 3
(zu größeren Teilen überprüft)
Umfang: 4
(unwichtige Fakten fehlen)
Quellenangaben: 3
(wichtige Quellen vorhanden)
Quellenarten: 5
(ausgezeichnet)
Konformität: 3
(gut)

Vorlesung WebProg

Inhalt | Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5 | Teil 6 | Vue 1 | Vue 2 | Vue 3 | Vue 4 | Vue 5 | Vue 6

Musterlösung
index.html (HTML validate, CSS validate, Google PageSpeed)
Git-Repository

Anwendungsfälle (Use Cases)

Gegenüber dem dritten, vierten und fünften Teil des Tutoriums ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.

In diesem Teil des Tutoriums geht es darum, den CSS-Code „DRY zu machen“.

Erstellen eines neuen Projekts

Erstellen Sie ein neues Projekt hello_world_06 als Fork von hello_world_05.

CSS-Erweiterungen

CSS bietet heute dieselbe Funktionalität wie Transpiler (SASS, Less etc.), die früher verwendet wurden, um fehlende Funktionalität in CSS zu integrieren. Ich werde in diesem Semester CSS an Stelle von SCSS einsetzen, so wie es von vite empfohlen wird:

Because Vite targets modern browsers only, it is recommended to use native CSS variables with PostCSS plugins that implement CSSWG drafts (e.g. postcss-nesting) and author plain, future-standards-compliant CSS. (https://vite.dev/guide/features)

Eine ganz wesentliche Erweiterung ist die Möglichkeit Konstanten zu definieren. Auch die Möglichkeit, Werte zu berechnen, gibt es in der Zwischenzeit (SCSS: math, CSS: calc). Es ist jetzt auch möglich CSS-Elemente zu verschachteln. Das heißt, die Bedeutung von SCSS, Less etc. schwindet.

CSS-Konstanten

Eine ganz wesentliche Erweiterung ist die Möglichkeit Konstanten zu definieren, da man damit CSS-Code DRY formulieren kann.

Wenn eine Konstante definiert wurde, kann man im übrigen CSS-Code mittels var darauf zugreifen (und nicht etwa mittels const, :-( )

:root 
{ --font-family-serif: "Times New Roman", Times, serif; }

p
{ font-family: var(--font-family-serif); }

label
{ font-family: var(--font-family-serif); }

Auch die Möglichkeit, Werte zu berechnen, gibt es in der Zwischenzeit (SCSS: math, CSS: calc). Das heißt, die Bedeutung von SCSS, Less etc. schwindet. In diesem Semester verwende ich nicht mehr SCSS, sondern nur noch CSS.

Fügen Sie "config" als Abkürzung für "./src/css/_config.css" in die Datei vite.config.js ein.

...
  resolve:
  { alias:
    { ...
      'config.css': fileURLToPath(new URL('./src/css/_config.css', import.meta.url)),
      ...
    }
  }
...

In der Datei _config.css werden Konstanten definiert, die von allen anderen CSS-Dateien verwendet werden können und sollen.

Das heißt, das DRY-Prinzip „Konstanten gehören nicht in den Code, sondern in Konfigurationsdateien“ wird ab sofort beachtet.

Wenn man künftig am Layout einen Zeichensatz, eine Farbe, einen Hintergrund oder Ähnliches ändern will, reicht es, die entsprechenden Konstanten anzupassen und schon erzeugt Vite automatisch aktualisiere CSS-Dateien.

Durch den CSS-Import-Befehl ist es möglich, CSS-Dateien zu modularisieren. Der Underscore _ am Beginn des Dateinamens deutet an, dass diese CSS-Datei nur von anderen CSS-Dateien aber nicht von HTML- oder JavaScript-Dateien importiert werden sollte.

src/css/_config.css

:root
{ --background-color:  #C5EFFC;

  --font-family-sans:  Verdana, Helvetica, sans-serif;
  --font-family-serif: "Times New Roman", Times, serif;
  
  --font-size-base:    3vw;
  --font-size-factor:  1.25;  /* cmp. https://type-scale.com/ */
   
  --font-size-h5:      calc(pow(var(--font-size-factor),1)*var(--font-size-base));
  --font-size-h4:      calc(pow(var(--font-size-factor),2)*var(--font-size-base));
  --font-size-h3:      calc(pow(var(--font-size-factor),3)*var(--font-size-base));
  --font-size-h2:      calc(pow(var(--font-size-factor),4)*var(--font-size-base));
  --font-size-h1:      calc(pow(var(--font-size-factor),5)*var(--font-size-base));
  
  --font-size-p:       calc(pow(var(--font-size-factor),0)*var(--font-size-base));
  --font-size-p-large: calc(pow(var(--font-size-factor),2)*var(--font-size-base));
  
  --font-size-small:   calc(pow(var(--font-size-factor),-1)*var(--font-size-base));
}

In dieser CSS-Datei werden folgende modernen CSS-Konstrukte verwendet:

  • Definition von Konstanten (die teilweise per Berechnung ermittelt werden)
  • Mathematische Berechnungen: calc

Konstanten starten in CSS mit zwei Minuszeichen. Sobald eine Konstante definiert wurde, kann sie in allen weiteren CSS-Konstrukten verwendet werden. In CSS stehen einen Operatoren zur Verfügung wie +, -, * und /, um Maße zu berechnen. Es gibt weitere Operatoren zum Vergleichen von Zahlen und Maßen sowie zur Berechnung von Strings und booleschen Werten: https://sass-lang.com/documentation/operators.[1]

Die Datei _config.css kann nun mit Hilfe des CSS-Befehls @import 'config.css'; (ohne Underscore und ohne .css, wegen des zuvor eingeführten Vite-Aliases) in die anderen beiden CSS-Dateien eingefügt werden.

PostCSS

Der Inhalt der Datei _config.css wird defaultmäßig an den Browser ausgeliefert, obwohl sie nur CSS-Konstanten enthält. Beim Einsatz vom SCSS werden Konstanten vom SCSS-Präprozessor auf dem Server während des Build-Prozesses durch ihre Werte ersetzt. In CSS muss dies defaultmäßig der Browser übernehmen. Es gibt allerdings ein PostCSS-Plugin postcss-var-replace, das diese Ersetzungen ebenfalls während des Build-Prozesses vornimmt. Dieses kann man in die Vite-Konfiguration integrieren:

Laden sie das Pluging postcss-var-replace:

npm i -D postcss-var-replace

Anschließend aktivieren Sie es in vite.config.js

import { postcssVarReplace }  from 'postcss-var-replace';

...

export default
{ ...
  css:
  { postcss:
    { plugins: 
      [ postcssVarReplace(),
      ],
    },
  },
  ...
}

Der Import-Befehl hat ab sofort erst dann einen Effekt, wenn in den anderen Dateien auf diese Konstanten zugegriffen wird. Aber er schadet auch nicht, wenn auf keine der dort definierten Konstanten zugegriffen wird. Der Import-Befehl selbst taucht ebenso wenig in den generierten CSS-Dateien auf, wie die Konstantendefinitionen. Der PostCSS-Transpiler ersetzt Konstanten in CSS-Definitionen durch ihren jeweiligen Wert.

Sie können nun beispielsweise in der Datei head.css die Konstante --background-color verwenden. In dem daraus durch den Build-Befehl npm run build erzeugten CSS-Style-Element steht weiterhin der Farbwert #C5EFFC;

src/css/head.css

@import 'config.css';

body
{ background-color: var(--background-color); }
 
.hidden
{ display: none; }

Die Datei body.css ist deutlich umfangreicher. Daher wird der zugehörige CSS-Code ja auch erst dynamisch gemeinsam mit der Datei web/js/main.js geladen.

src/css/body.css

@import 'config.css';

html
{ height:  100%;
  width:   100%;
  display: table;
}

body
{ display:          table-cell;
  text-align:       center;
  vertical-align:   middle;
  font-size:        var(--font-size-base);
  font-family:      var(--font-family-sans);
}

h1
{ padding:   0;
  margin:    0;
  font-size: var(--font-size-h1);
}

p, label
{ font-family: var(--font-family-serif);
  font-size:   var(--font-size-p);
}

label, input
{ width:      10em;
  font-size:  100%;
  display:    inline-block;
  box-sizing: border-box;
  margin:     0.5ex;
}

label
{ text-align: right;
}

#section_form
{ text-align:   center;
  margin-left:  auto;
  margin-right: auto;

  h1
  { margin-bottom: 0.5ex; }
}

#section_hello
{ p
  { font-size: var(--font-size-p-large) !important; }
}

In dieser CSS-Datei werden folgende modernen CSS-Befehle verwendet:

  • Import-Befehl: @import 'config.css';
  • Konstanten: --font-family-sans, --font-size-base etc. (Es sind noch viele weitere konstante Werte in body.css enthalten, für die in _config.css Konstanten definiert werden sollten)
  • Verschachtelte Anweisungen: z. B. h1 innerhalb von #section_form

Die verschachtelten Anweisungen strukturieren den CSS-Code deutlich besser. Es ist nicht mehr notwendig, einen Selektor wie #section_form mehrfach zu verwenden.

Sehen Sie sich den Unterschied an. In der Datei src/css/body.css der Musterlösungen vom dritten Teil des Tutoriums hatte ich Folgendes geschrieben:

#section_form
{ text-align:   center;
  margin-left:  auto;
  margin-right: auto;
}

#section_form > h1
{ margin-bottom: 0.5ex; }

Die modernen CSS-Variante ist deutlich strukturierter und prägnanter.

#section_form
{ text-align:   center;
  margin-left:  auto;
  margin-right: auto;

  h1
  { margin-bottom: 0.5ex; }
}

Insbesondere bei großen CSS-Dateien erweist sich diese kompaktere Schreibweise als vorteilhaft.

Fortsetzung des Tutoriums

Sie sollten nun Teil 1 des Vue-Tutoriums bearbeiten. In diesem Teil des Tutoriums wird die oben erstelle Variante in das Vue-Framework transferiert.

Quellen

  1. Kowarschick (WebProg): Wolfgang Kowarschick; Vorlesung „Web-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2024; Quellengüte: 3 (Vorlesung)