per user-request einen branch der main-content UND rewrite-content trägt — saubere separierung statt symlink/merge-conflict. struktur: - slides/<course>/ → main-content restored, eigene assets (kein new-demo-leak) - slides/<course>-2026/ → rewrite-content, eigene assets (komplett kopiert + new demos) Makefile: COURSES += 223015b-2026 223015c-2026 dhbw-2026 mit eigenen NAME/KAPITEL/DEPLOY/KLAUSUR-konfig. Klausur für b+c=1, dhbw=leer. Deploy-paths /hdm/223015b-2026 etc. make build durchlaufen für alle 6 decks, 0 fehler. dedup: 223015c+dhbw assets identisch in beiden ordnern (kein neu-demos auf b ergänzt). 223015b 86 → 120 files in -2026 (= +34 neue eroeffner/usb-c-drei-achsen/container-vs-codec/etc).
7.2 KiB
marp, theme, paginate, backgroundColor, header, footer
| marp | theme | paginate | backgroundColor | header | footer |
|---|---|---|---|---|---|
| true | gaia | true | Web Engineering – DHBW Stuttgart | Michael Czechowski – SoSe 2026 |
Kapitel 3 — Node.js Basics
JavaScript außerhalb des Browsers
Was ist Node.js?
Ryan Dahl, 2009. JavaScript-Runtime auf V8 (Chrome's JS-Engine).
Vorher: JS war Browser-only. Mit Node: JS auch als Server, CLI-Tools, Build-Skripte.
Heute: Node ist Standard-Backend für viele Web-Apps. Netflix, LinkedIn, NASA, Walmart.
Warum Node?
| Vorteil | Was bedeutet das |
|---|---|
| JS überall | gleiche Sprache Frontend + Backend |
| NPM | größtes Package-Ökosystem (~3 Mio Packages) |
| Non-blocking I/O | viele Verbindungen gleichzeitig |
| Schnell genug | V8 optimiert JS aggressiv |
| Cross-platform | Linux, macOS, Windows |
Node Versions-Manager
fnm (oder nvm, volta) — pro Projekt Node-Version.
# Installieren (macOS/Linux)
brew install fnm # oder curl-script
# Aktuelle LTS
fnm install --lts
fnm use lts-latest # 24.x
# Pro Projekt
echo "24" > .nvmrc
fnm use # liest .nvmrc
Aktuell: Node 24 LTS.
Projekt initialisieren
mkdir mein-projekt && cd mein-projekt
npm init -y # erzeugt package.json
# Abhängigkeiten installieren
npm install express # → dependencies
npm install -D vitest # → devDependencies (nur dev)
# Skripte ausführen
npm run start
npm test
-y = alle Defaults akzeptieren.
package.json
{
"name": "mein-projekt",
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "node --watch src/server.js",
"start": "node src/server.js",
"test": "vitest"
},
"dependencies": {
"express": "^5.0.0"
},
"devDependencies": {
"vitest": "^2.0.0"
}
}
"type": "module" aktiviert ESM.
ESM — modern
// utils.js
export function greet(name) {
return `Hallo ${name}`;
}
export const VERSION = "1.0";
// main.js
import { greet, VERSION } from './utils.js';
console.log(greet('Ada'), VERSION);
Pflicht: .js-Endung in import-Pfad.
CommonJS — Legacy
// utils.cjs
function greet(name) {
return `Hallo ${name}`;
}
module.exports = { greet };
// main.cjs
const { greet } = require('./utils.cjs');
Wann CJS? Alte Codebases, npm-Packages, die nicht migriert sind. Default heute: ESM.
Built-in Modules
import { readFile } from 'node:fs/promises';
import { createServer } from 'node:http';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
node: Prefix macht explizit klar — kein npm-Package.
HTTP-Server
Eingebauter HTTP-Server
import { createServer } from 'node:http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hallo Welt');
});
server.listen(3000, () => {
console.log('Server läuft auf :3000');
});
Nackt — ohne Framework. Funktioniert.
Express — der Klassiker
import express from 'express';
const app = express();
app.use(express.json()); // parsed JSON-Body
app.use(express.static('public')); // statische Dateien
app.get('/', (req, res) => {
res.send('Hallo Welt');
});
app.post('/api/echo', (req, res) => {
res.json({ youSent: req.body });
});
app.listen(3000);
REST mit Express
const users = [{ id: 1, name: 'Ada' }];
app.get('/users', (req, res) => res.json(users));
app.get('/users/:id', (req, res) => {
const user = users.find(u => u.id == req.params.id);
user ? res.json(user) : res.sendStatus(404);
});
app.post('/users', (req, res) => {
const user = { id: users.length + 1, ...req.body };
users.push(user);
res.status(201).json(user);
});
Alternative Frameworks
| Framework | Stärke |
|---|---|
| Express | etabliert, größte Community |
| Fastify | schneller, schemas eingebaut |
| Hono | leichtgewichtig, Edge-deployable |
| Koa | von Express-Autoren, modern |
Für DHBW: Express oder Hono.
Routing-Pattern
import { Router } from 'express';
const userRouter = Router();
userRouter.get('/', (req, res) => { /* alle Users */ });
userRouter.get('/:id', (req, res) => { /* ein User */ });
userRouter.post('/', (req, res) => { /* User anlegen */ });
userRouter.put('/:id', (req, res) => { /* User update */ });
userRouter.delete('/:id', (req, res) => { /* User löschen */ });
app.use('/users', userRouter); // mountet unter /users/*
Fetch in Node
fetch — global ab Node 18
// GET
const res = await fetch('https://api.github.com/users/torvalds');
const data = await res.json();
console.log(data.public_repos);
// POST
const post = await fetch('https://api.example.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'Hallo' })
});
Genau wie im Browser. Kein extra Package (vorher: node-fetch, axios).
Error-Handling
try {
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
return data;
} catch (error) {
console.error('API call failed:', error.message);
throw error; // re-throw für caller
}
res.ok ist true für 2xx-Statuscodes.
Environment Variables
// .env (gitignored!)
DATABASE_URL=postgres://...
API_KEY=sk-...
PORT=3000
// src/config.js
import 'dotenv/config';
export const config = {
port: process.env.PORT || 3000,
dbUrl: process.env.DATABASE_URL,
apiKey: process.env.API_KEY,
};
Niemals API-Keys ins Repo committen.
Selbstlernen — Mini-API
- Projekt initialisieren:
npm init -y, ESM aktivieren - Express installieren
- REST-API für eine Ressource (Books / Movies / TODO)
GET /items,GET /items/:id,POST /items,DELETE /items/:id
- In-Memory-Store als Array (echte DB kommt Kap 4)
- Mit Hoppscotch oder curl testen
Bonus: npm run dev mit --watch-Flag.
Zusammenfassung
Heute gelernt:
- Node.js als JS-Runtime außerhalb Browser
- fnm + Node 24 LTS als Versions-Setup
- npm init, package.json, scripts, dependencies
- ESM (import/export) als modernes Modul-System
- Built-in HTTP-Server + Express für REST
- fetch global ab Node 18
- .env + dotenv für Secrets
Nächste Stunde: async/await, Filesystem, Datenbank, Auth.