Files
uni/slides/dhbw/01_web_eng.md
T
libretech 722a4a9fe8 slides: 8 overflow-folien gefixt + fragmented-list-marker eingeführt
per user-feedback nach QA-render-check aller 493 folien (overflow-detector via PIL bottom-band-darkness):

223015b/01-daten-grundlagen s.036 nyquist:
  H1 'Nyquist-Theorem — warum 2× reicht' → 'Nyquist — warum 2× reicht'
  body text gekürzt, drei fälle als * statt - (marp fragmented list)

223015b/03-inhalte-bild-audio-video s.009 RGB→Y'CbCr:
  H1 verkürzt, bg right 50% → 45% contain, list-marker * (Y/Cb/Cr reveal)
  text 'unabhängig komprimiert werden' eingedampft

223015b/03-inhalte-bild-audio-video s.031 inter-frame:
  H1 'Inter-Frame-Kompression — die zentrale Idee' → 'Inter-Frame — die zentrale Idee'
  bg right 42% → 40% contain
  bullets I/P/B mit * (fragmented reveal)

223015b/05-distribution-metadaten s.012 EXIF-tabelle:
  8 zeilen → 5 zeilen (kamera+linse zusammengelegt, belichtung kompakt, software+bearbeitung zusammengelegt)

223015b/05-distribution-metadaten s.014 EXIF-stripping:
  7 plattform-zeilen → 5 (facebook+iMessage und E-mail+slack+discord zusammen)
  faustregel als italic-zeile statt bold-block

223015c/01-geschichte-grundlagen-html s.006 alan turing:
  bg right 35% (default fill) → 33% contain (verhindert dass composite-bild bis footer reicht)
  3 jahres-zeilen als * bullets (fragmented reveal)

dhbw/01_web_eng s.054 counter:
  in 2 folien gesplittet: 'Counter — Vanilla + React' und 'Counter — Vue + Svelte'
  pointe 'vier frameworks, dasselbe pattern: state → UI re-rendert' am ende der 2. folie

dhbw/08_best_practices s.005 .gitignore:
  code-block gekürzt: 6 sektionen → 5, mehrere lines pro logical group zusammengezogen (pem+key zusammen, vscode+idea zusammen)
  github.com/github/gitignore als markdown-link

bonus: wo pädagogisch sinnvoll - durch * ersetzt (marp progressive-reveal in presenter-modus). nicht überall — nur wo bullets sequenziell aufgedeckt werden sollten.

klausurfolien regeneriert (223015b 27, 223015c 19)
2026-05-14 20:48:38 +02:00

838 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
title: Web Engineering
---
<style>
:root { --color-foreground: #1a1a2e; --color-highlight: #d63384; --color-dimmed: #4a4a6a; }
section.invert { --color-foreground: #fff; }
section { font-size: 1.4rem; }
h1 { color: #a02060; }
section.invert h1 { color: #fff; }
h2 { color: #1f2937; }
section.invert h2 { color: #f48fb1; }
pre { background: #0f0f23; color: #f48fb1; border-radius: 8px; border-left: 3px solid #d63384; }
pre code { background: transparent; color: inherit; }
code { background: #1a1a2e; color: #f48fb1; padding: 0.15em 0.4em; border-radius: 4px; }
a { color: var(--color-highlight); }
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
![bg cover opacity:0.2](./assets/background.png)
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026**
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** — [developer.mozilla.org](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
---
<!-- _class: lead -->
# Herzlich Willkommen!
## 1. Sitzung: 08.05.2026
---
# Über mich
![bg right:33% fit](./assets/logos/collage.png)
Michael Czechowski
- Software Engineer, ehemals freischaffend
- Lektor an HdM Stuttgart + DHBW
- librete.ch
---
# Vorlesungsplan (Auszug)
| Termin | Thema |
|--------|-------|
| 1 | Web Engineering (heute) |
| 2 | CSS Extended |
| 3 | Node.js Basics |
| 4 | Node.js Advanced |
| 5 | Testing |
| 6 | TypeScript |
| 7 | Docker |
| 8 | Best Practices |
---
# Prüfungsleistung — 75 P + 10 Bonus
**Projekt-Abgabe** statt Klausur.
| Bereich | Punkte |
|---------|-------:|
| Projekt-Struktur + README | 10 |
| Code-Qualität | 15 |
| Git-Hygiene | 10 |
| Tests | 10 |
| Docker | 10 |
| HTTP / API | 10 |
| Frontend + A11y | 10 |
| Präsentation + Bonus | 5 + 10 |
---
<!-- _class: lead -->
# Kontext: was ist „das Web"?
---
# Internet-Timeline
| Jahr | Was |
|------|-----|
| 1969 | ARPANET — 4 Knoten |
| 1971 | Email (Ray Tomlinson, `@`) |
| 1983 | TCP/IP-Standard |
| **1989** | **WWW** (Berners-Lee, CERN) |
| 1993 | Mosaic-Browser → Web wird populär |
---
# Das WWW (1989)
**Tim Berners-Lee am CERN.** Drei Standards:
- **HTTP** — Protokoll
- **HTML** — Format
- **URL** — Adresse
Patentfrei → Web konnte explodieren.
---
# Heute: physische Infrastruktur
- ~400 Unterseekabel
- 1,3 Mio km Glasfaser weltweit
- DE-CIX Frankfurt: größter Internet-Knoten (~12 Tbit/s)
Das Web ist **physisch.**
---
# URL → Pixel in 7 Schritten
1. **URL parsen** — Schema, Host, Port, Path
2. **DNS-Lookup** — Host-Name → IP
3. **TCP-Handshake** mit Server
4. **TLS-Handshake** (https)
5. **HTTP-Request** senden
6. Server antwortet mit **HTML + CSS + JS**
7. Browser **parsed + rendert** → Pixel
---
# HTTP — Anatomie
```http
GET /index.html HTTP/1.1
Host: librete.ch
User-Agent: Mozilla/5.0 ...
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
<!DOCTYPE html>...
```
**Statuscodes:** 200 OK · 301 Moved · 404 Not Found · 500 Server Error
---
<!-- _class: lead -->
# Onboarding
## Tools, Runtimes, Workflows
---
# Werkzeuge & Betriebssystem
| Bereich | Empfehlung |
|---------|------------|
| Editor | **VS Code** · JetBrains (edu lizenz frei) |
| Browser | **Chromium / Firefox** |
| Terminal | macOS Terminal · Linux Terminal · Windows Terminal |
| Paket-Manager | macOS: brew · Linux: apt/dnf · Windows: winget/scoop/choco |
| Versions-Control | Git + GitHub/Gitea |
---
# Node.js installieren
**Best Practice:** Versions-Manager statt Direkt-Install.
| OS | Empfehlung |
|----|------------|
| macOS | `brew install fnm` → `fnm install --lts` |
| Linux | `curl -fsSL https://fnm.vercel.app/install \| bash` |
| Windows | `winget install Schniz.fnm` |
**Aktuelle LTS:** Node 24.
---
# Warum Versions-Manager?
**Direkt-Install** (z.B. `brew install node`) bringt Probleme:
- Projekt-A braucht Node 18, Projekt-B braucht Node 22 → Konflikt
- Update bricht alte Projekte
- Kein automatisches Switching pro Projekt
**fnm / nvm / volta:** pro Projekt Node-Version, automatisch via `.nvmrc`.
---
# Alternative Runtimes
| Runtime | Stärke |
|---------|--------|
| **Node** | Standard, größtes Ökosystem |
| **Deno** | Sicher by default, TypeScript nativ |
| **Bun** | Schnell, all-in-one (runtime + bundler + tester) |
Für DHBW-Kurs: **Node 24 LTS.**
---
# Browser DevTools
**F12** öffnet das Power-Tool jeder Webentwicklung.
| Tab | Wofür |
|-----|-------|
| Elements | DOM-Baum inspizieren + live editieren |
| Console | JS ausführen, Errors lesen |
| Network | HTTP-Requests sehen, Latenz |
| Performance | Render + Memory profilen |
| Lighthouse | A11y · SEO · Perf-Audit |
---
# HTTP-Clients
Tools zum Testen von APIs:
- **curl** — CLI, überall
- **Hoppscotch** — Browser, Open Source
- **Postman** — GUI, kommerziell
- **VS Code REST Client** — Plugin
---
# Git Setup
```sh
git config --global user.name "Dein Name"
git config --global user.email "du@dhbw.de"
git config --global init.defaultBranch main
git config --global core.autocrlf input # Windows: true
```
**SSH-Key** für GitHub/Gitea ohne Passwort-Prompt:
```sh
ssh-keygen -t ed25519 -C "du@dhbw.de"
cat ~/.ssh/id_ed25519.pub # zu GitHub kopieren
```
---
# Projekt-Skeleton
```
mein-projekt/
├── .git/
├── .gitignore # node_modules/, .env, build/
├── README.md # was, wie, warum
├── package.json # npm metadata + scripts
├── src/ # eigener Code
├── public/ # statische Assets (für Web)
├── tests/ # Unit + Integration
└── Dockerfile # für Container-Deploy
```
---
<!-- _class: lead -->
# HTML
## Hypertext Markup Language
---
# Was ist HTML?
**Tim Berners-Lee, 1989.** Struktur-Format des Webs.
**Syntax:** Tags mit Attributen umfassen Inhalt.
**Browser parst HTML** → DOM (Document Object Model) → rendert.
Plain-Text mit Tags. Lesbar mit jedem Editor.
---
# HTML-Anatomie
```html
<a href="https://librete.ch" target="_blank">Mein Link</a>
```
- `<a` — Opening-Tag mit Tag-Namen
- `href="..."` — Attribut (Name + Wert)
- `Mein Link` — Inhalt
- `</a>` — Closing-Tag
- Alles zusammen = **Element**
---
# Self-closing Tags
```html
<img src="foto.jpg" alt="Sonnenuntergang">
<br>
<input type="text" name="username">
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
```
Kein Closing-Tag. Inhalt aus Attributen + (für `<input>`) User-Eingabe.
---
# Document-Grundgerüst
```html
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Meine Seite</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hallo Welt</h1>
</body>
</html>
```
---
# Semantische HTML-Tags
| Tag | Bedeutung |
|-----|-----------|
| `<header>` | Kopfbereich (Logo, Nav) |
| `<nav>` | Navigation |
| `<main>` | Hauptinhalt |
| `<section>` | Thematischer Abschnitt |
| `<article>` | eigenständiger Inhalt |
| `<aside>` | Seiten-Inhalt |
| `<footer>` | Fußbereich |
**Pflicht** für SEO + A11y + Wartbarkeit.
---
# Native HTML-Elemente — nicht vergessen!
Bevor du eine Custom-Component baust: **gibt's das schon nativ?**
| Element | Was |
|---------|-----|
| `<details>` / `<summary>` | Accordion ohne JS |
| `<dialog>` | Modal mit Native Backdrop |
| `<input type="date">` | Date-Picker, native, A11y |
| `<input type="color">` | Color-Picker |
| `<input type="range">` | Slider |
| `<datalist>` | Autocomplete-Vorschläge |
| `<progress>` | Lade-Balken |
**Faustregel:** Native zuerst, Custom nur wenn nötig.
---
<!-- _class: lead -->
# Barrierefreiheit
## A11y — Accessibility
---
# BFSG + EAA — Pflicht ab 28.06.2025
**Barrierefreiheitsstärkungsgesetz** (DE) setzt **European Accessibility Act** (EU) um.
**Pflicht:**
- Online-Shops, Banken, Versicherungen
- E-Books, Buchungssysteme
- Smartphone-Apps mit kommerziellem Bezug
**Ausnahme:** < 10 Mitarbeiter + < 2 Mio € Umsatz.
**Strafe:** bis 100.000 € Bußgeld + Klage durch Behindertenverbände.
---
# Wie nutzen Menschen das Web?
- **Sehen:** Screen-Reader (NVDA, JAWS, VoiceOver)
- **Hören:** Untertitel + Transkripte
- **Motorik:** Tastatur statt Maus, Switch-Control
- **Kognitiv:** klare Sprache, viel Whitespace
- **Vorübergehend:** Sonne im Bildschirm, gebrochener Arm, ÖPNV-Lärm
~10 % der Bevölkerung haben relevante Beeinträchtigungen. *Du auch — irgendwann.*
---
# WCAG · 4 Prinzipien (POUR)
| Prinzip | Was |
|---------|-----|
| **P**erceivable | Alt-Text · Untertitel · Kontrast |
| **O**perable | Keyboard · Skip-Links |
| **U**nderstandable | klare Sprache · Fehler-Hilfe |
| **R**obust | semantisches HTML · Standards-konform |
**WCAG 2.1 Level AA** = Mindest-Standard für BFSG.
---
# Perceivable — wahrnehmbar
- **Alt-Text** für jedes Bild (`<img alt="...">`)
- **Untertitel** für jedes Video
- **Kontrast 4.5:1** für Text (Level AA)
- **Skalierbar** bis 200 %
```html
<img src="foto.jpg" alt="Sonnenuntergang am Bodensee">
<!-- LEER alt="" für rein dekorative Bilder -->
```
---
# Operable — bedienbar
- Alle interaktiven Elemente **mit Tastatur erreichbar**
- **Fokus sichtbar** (`:focus-visible` mit Outline)
- **Skip-Links** für Screen-Reader (Hauptnav überspringen)
- **Genug Zeit** für Aufgaben (Auto-Logout pausierbar)
```css
button:focus-visible {
outline: 3px solid hotpink;
outline-offset: 2px;
}
```
---
# Understandable — verständlich
- **Lese-Niveau** angemessen (Level AA: 9. Klasse)
- **Klare Fehlermeldungen** (was war falsch, wie korrigieren)
- **Konsistente Navigation** (Header bleibt gleich)
- **`lang`-Attribut** im html-Element
```html
<html lang="de">
<p lang="en">This sentence is in English.</p>
</html>
```
---
# Robust — Tech-stabil
- **Semantisches HTML** statt div-Suppe
- **ARIA** *nur als Ergänzung*, nicht als Ersatz
- **Standards-konform** (Validator: validator.w3.org)
```html
<!-- ❌ semantisch falsch -->
<div onclick="...">Klick</div>
<!-- ✓ semantisch korrekt -->
<button onclick="...">Klick</button>
```
---
# A11y-Testen — Werkzeuge
| Tool | Was |
|------|-----|
| **Lighthouse** (Chrome DevTools) | automatischer Audit |
| **axe DevTools** | Plugin, präziser |
| **WAVE** | Browser-Plugin, visuell |
| **Manuell** | Maus weglegen, nur Tab |
| **Screen-Reader** | macOS: VoiceOver (Cmd+F5) · Win: NVDA |
**Automatisierte Tools** finden ~30 %. Rest = manuell.
---
<!-- _class: lead -->
# CSS
## Cascading Style Sheets
*(Vertiefung in Kap 2 — CSS Extended)*
---
# CSS einbinden
```html
<!-- External (best practice) -->
<link rel="stylesheet" href="./style.css">
<!-- Internal -->
<style>
body { background: #fafafa; }
</style>
<!-- Inline (vermeiden) -->
<button style="background: hotpink">Klick</button>
```
---
# CSS-Anatomie
```css
button {
background-color: hotpink;
padding: 10px 20px;
border-radius: 8px;
}
```
- `button` = **Selektor** (welche Elemente)
- `background-color` = **Property**
- `hotpink` = **Value**
- alles in `{ }` = **Declaration Block**
---
# Selektoren
| Selektor | Was |
|----------|-----|
| `p` | alle `<p>` |
| `.btn` | alle mit `class="btn"` |
| `#header` | das Element mit `id="header"` |
| `button:hover` | Button beim Hover |
| `nav > a` | direkte `<a>` unter `<nav>` |
| `*` | alles |
---
# Spezifizität — wer gewinnt?
```css
p { color: blue; } /* 1 */
.notice { color: red; } /* 10 */
#warn { color: green; } /* 100 */
[style] /* inline */ /* 1000 */
```
**Inline > ID > Klasse > Element.** Bei Gleichstand: **letzte Regel.**
`!important` umgeht alles — *vermeiden.*
---
# Box-Model
```
┌──────────────────────┐
│ margin │
│ ┌────────────────┐ │
│ │ border │ │
│ │ ┌──────────┐ │ │
│ │ │ padding │ │ │
│ │ │ content │ │ │
│ │ └──────────┘ │ │
│ └────────────────┘ │
└──────────────────────┘
```
**Best Practice:** `* { box-sizing: border-box; }` global.
---
# Farben
| Notation | Beispiel |
|----------|----------|
| Hex | `#FF5733` |
| RGB | `rgb(255, 87, 51)` |
| RGBA | `rgb(255, 87, 51, 0.5)` |
| HSL | `hsl(11, 100%, 60%)` |
| OKLCH (modern) | `oklch(0.7 0.2 30)` |
| Schlüsselwort | `hotpink`, `tomato` |
---
# Einheiten
| Einheit | Was |
|---------|-----|
| `px` | Pixel, fix |
| `rem` | relativ zu Wurzel-Font (16 px default) |
| `em` | relativ zu Eltern-Font |
| `%` | relativ zur Eltern-Größe |
| `vw` / `vh` | Viewport-Breite/-Höhe |
| `ch` | Breite eines Zeichens |
**Faustregel:** Font + Spacing in `rem`. Layout in `%` oder `fr`.
---
# Pseudo-Klassen & -Elemente
```css
/* Pseudo-Klassen (Zustand) */
a:hover { color: hotpink; }
input:focus { outline: 2px solid; }
button:disabled { opacity: 0.5; }
li:nth-child(2n) { background: #eee; }
/* Pseudo-Elemente (Virtuelles) */
p::first-letter { font-size: 2em; }
.tooltip::after { content: " 💡"; }
```
---
<!-- _class: lead -->
# JavaScript
## Die Sprache des Webs
*(Vertiefung in Kap 3+4 — Node.js)*
---
# ECMAScript
**ECMA International** (Schweiz) standardisiert die Sprache.
| Version | Jahr | Highlight |
|---------|------|-----------|
| ES5 | 2009 | strict mode, JSON |
| ES6 / 2015 | 2015 | `let` `const`, arrow, classes, modules |
| ES2017 | 2017 | async/await |
| ES2020 | 2020 | optional chaining `?.` |
| ES15 | 2024 | aktuell |
---
# JavaScript-Grundlagen
```javascript
// Variablen
const name = "Ada";
let alter = 56;
// Funktionen
const begrüßen = (name) => `Hallo ${name}`;
// Arrays + Objects
const fruits = ["A", "B"];
const user = { name: "Ada", admin: true };
// Schleifen
fruits.map(f => f.toUpperCase());
// async
async function laden() {
const res = await fetch('/api');
return res.json();
}
```
---
# DOM Manipulation
```javascript
// Element finden
const btn = document.querySelector('#myBtn');
// Inhalt ändern
btn.textContent = 'Neu';
btn.classList.add('active');
// Event-Handler
btn.addEventListener('click', () => {
console.log('Klick!');
});
// Element erzeugen
const li = document.createElement('li');
li.textContent = 'Item';
document.querySelector('ul').appendChild(li);
```
---
# Fetch + JSON
```javascript
// GET
const res = await fetch('https://api.github.com/users/torvalds');
const data = await res.json();
console.log(data.public_repos);
// POST
await fetch('/api/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'Hallo', body: '...' })
});
```
---
<!-- _class: lead -->
# Frameworks-Vorschau
---
# Framework-Landschaft
| Framework | Typ | Use-Case |
|-----------|-----|----------|
| **React** | Library | dominant, große Community |
| **Vue 3** | Framework | sanfter Einstieg |
| **Svelte** | Compiler | kein Virtual DOM, kleines Bundle |
| **Astro** | Hybrid | Content-First, Multi-Framework |
| **Angular** | Framework | Enterprise, Google |
Alle: **Komponenten + reaktive State + Re-Render.**
---
# Counter — Vanilla + React
**Vanilla JS:**
```javascript
let count = 0;
btn.onclick = () => { count++; display.textContent = count; };
```
**React (JSX):**
```jsx
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
```
---
# Counter — Vue + Svelte
**Vue 3 (Composition):**
```vue
<script setup>const count = ref(0)</script>
<template><button @click="count++">{{ count }}</button></template>
```
**Svelte:**
```svelte
<script>let count = 0</script>
<button on:click={() => count++}>{count}</button>
```
Vier Frameworks, **dasselbe Pattern:** State → UI re-rendert.
---
# Build-Tools
| Tool | Stärke |
|------|--------|
| **Vite** | schnell, modern, Default für React/Vue/Svelte |
| **Webpack** | etabliert, mächtig, verbreitet |
| **Parcel** | zero-config |
| **Bun** | all-in-one, sehr schnell |
**Heute:** Vite ist der Default für neue Projekte.
---
# Rendering-Modi
| Modus | Wann |
|-------|------|
| **CSR** (Client-Side) | Single-Page-Apps (Dashboard, Editor) |
| **SSR** (Server-Side) | SEO + erste Latenz wichtig (News, Shop) |
| **SSG** (Static Site Gen) | reine Content-Sites (Blog, Doku) |
| **ISR** (Incremental SSG) | Hybrid: Content selten ändert |
Astro / Next.js / Nuxt unterstützen alle.
---
<!-- _class: aufgabe -->
# Selbstlernen — Erste eigene Seite
1. **Mappe anlegen** `meine-seite/`
2. `index.html` mit dem **Grundgerüst** (DOCTYPE, head, body, h1, p)
3. `style.css` daneben — mit Hotpink-Background
4. **VS Code Live Server** starten → im Browser öffnen
5. **DevTools** auf, F12, Tab Elements → DOM-Baum anschauen
**Bonus:** Lighthouse Audit laufen lassen. Welchen Score erreicht ihr?
---
# Zusammenfassung
**Heute gelernt:**
- Internet-Geschichte → WWW → URL→Pixel-7-Schritte
- Onboarding-Stack: Node (fnm), VS Code, Git, DevTools
- HTML: Anatomie, semantisch, A11y-Foundation
- A11y: BFSG/EAA-Pflicht, WCAG POUR
- CSS-Basics (Vertiefung in Kap 2)
- JS-Basics (Vertiefung in Kap 3+4)
- Framework-Landschaft (Vorschau)
**Nächste Stunde:** CSS deeper — Flexbox, Grid, Responsive, Animations.