Files
uni/slides/dhbw/03_nodejs_basics.md
T
libretech 4053185e74 dhbw phase 4: alle 8 kapitel slide-MD komplett (4176 zeilen → ~1100 zeilen, ~210 slides total)
kap1 web_eng (104 → 57 slides): kurs-intro + prüfungsleistung-übersicht, internet-timeline (4 milestones), URL→pixel-7-schritte, HTTP, onboarding (node 24 LTS via fnm, brew/winget paket-manager, VS Code/Chromium/Hoppscotch, git setup mit SSH-key, projekt-skeleton), HTML (anatomie, self-closing, grundgerüst, semantik-tabelle, native elemente details/dialog/input-types), A11y volle tiefe (BFSG+EAA 28.06.2025, WCAG-POUR, Perceivable/Operable/Understandable/Robust einzeln mit code, testen mit lighthouse/axe/manuell), CSS-vorschau (anatomie/selektoren/spezifizität/box-model/farben/einheiten/pseudos), JS-vorschau (ECMAScript-timeline/grundlagen/DOM/fetch), frameworks-übersicht (react/vue/svelte/astro counter-vergleich), build-tools/rendering-modi, selbstlernen erste-eigene-seite

kap2 css_extended (13 → 28 slides): box-model + box-sizing global, flexbox basics+achsen+item-properties+typische-patterns, grid basics+areas+auto-layout, flexbox-vs-grid tabelle, mobile-first media queries, viewport-meta, fluid sizing mit clamp(), transitions (was performant), keyframe-animationen, prefers-reduced-motion pflicht, CSS-variablen + dark-mode-pattern, CSS functions (calc/clamp/gradient/oklch/filter), CSS-frameworks tabelle + tailwind pro/contra, selbstlernen flexboxfroggy+cssgridgarden

kap3 nodejs_basics (~22 → 20 slides): was-ist-node + warum-node-tabelle, fnm versions-manager + node 24 LTS + .nvmrc, npm init + package.json (mit type:module), ESM modern + CJS legacy, built-in modules (node: prefix), HTTP-server eingebaut + express, REST mit express (GET/POST/PUT/DELETE-pattern), alternative frameworks tabelle (fastify/hono/koa), routing-pattern mit Router, fetch global ab node 18, error-handling res.ok, environment variables mit dotenv + niemals committen, selbstlernen mini-API

kap4 nodejs_advanced (~24 → 22 slides): synchron-vs-asynchron, promise then-vs-async/await, sequenziell-vs-parallel + Promise.all, promise-methoden tabelle (all/allSettled/race/any), fs/promises lesen+schreiben, streams pipeline für große dateien, DB-übersicht SQLite/Postgres/MongoDB/Redis, better-sqlite3 prepared statements, ORM-übersicht (drizzle/prisma/knex), CRUD-pattern express+sqlite, auth-strategien tabelle, bcrypt für passwörter, JWT-pattern mit httpOnly+secure cookie, try/catch + error-klassen, globaler express-error-handler, selbstlernen REST+DB+auth

kap5 testing (~23 → 23 slides): test-pyramide 70%/20%/10%, vitest setup + describe/it/expect, AAA-pattern, matchers tabelle, TDD red-green-refactor mit konkretem beispiel, supertest für API-integration, test-DB :memory: + lifecycle hooks, mocking mit vi.spyOn (sparsam), playwright E2E mit role-based-locators, E2E-vs-unit tradeoffs, coverage realistisch (80% gut), CI mit github-actions, selbstlernen tests-schreiben

kap6 typescript (~30 → 19 slides): was-ist-TS + warum-tabelle, setup mit tsx + tsconfig.json + strict:true, basis-typen + any vermeiden, object-typen + interfaces + type-aliases, function-typen (Promise<T>), union + discriminated union + intersection, generics + constraints, built-in generics (Partial/Omit/Record), typ-inference (nicht über-annotieren), typen für REST-API mit express, zod runtime-validation + z.infer, any-vs-unknown-vs-never, best practices, selbstlernen API-zu-TS-migration

kap7 docker (~24 → 24 slides): auf-meinem-rechner-läufts problem, container-vs-VM tabelle, docker basics (image/container/dockerfile/registry), dockerfile hallo-welt, schichten + cache-optimierung, multi-stage build, base-image-größen tabelle (alpine ~180MB vs node ~1.1GB), .dockerignore, compose.yml beispiel, compose-commands, networking (service-namen als hostnamen), volumes (named vs bind), env+secrets, github-actions docker-build, registry-übersicht, health-checks, best-practices, selbstlernen app-dockerizen

kap8 best_practices (~30 → 28 slides): sinnvolle commits + conventional commits format, .gitignore template, branches+PRs workflow, README-template mit 6 sektionen, SOLID 5 prinzipien tabelle, S-single-responsibility + D-dependency-inversion mit code, 12-factor wichtigste (codebase/deps/config/processes/disposability), factor 3 config-in-env, factor 6 stateless-processes, SemVer MAJOR.MINOR.PATCH, package.json caret/tilde/exakt, code-reviews geben+nehmen + checkliste, doku-quellen tabelle (MDN/nodejs/npm/tc39/caniuse), stack-overflow gut-nutzen, AI-assistenten pro/contra (verstehen-nicht-kopieren), selbstlernen projekt-hygiene-check

build geht durch alle 8 kapitel-html+pdf
render-spot-check: cover-slide-dark-mode-invert, git-setup code-syntax-highlight, css-anatomie code-blocks — alle sauber

kein deploy, nur build+verify
2026-05-14 17:14:02 +02:00

7.2 KiB
Raw Blame History

marp, theme, paginate, backgroundColor, header, footer
marp theme paginate backgroundColor header footer
true gaia true Web Engineering – DHBW Stuttgart Michael Czechowski – SoSe 2026
<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; } 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>

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

  1. Projekt initialisieren: npm init -y, ESM aktivieren
  2. Express installieren
  3. REST-API für eine Ressource (Books / Movies / TODO)
    • GET /items, GET /items/:id, POST /items, DELETE /items/:id
  4. In-Memory-Store als Array (echte DB kommt Kap 4)
  5. 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.