--- marp: true theme: gaia paginate: true backgroundColor: #fff header: "Web Engineering – DHBW Stuttgart" footer: "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. ```sh # 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 ```sh 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 ```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 ```javascript // 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 ```javascript // 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 ```javascript 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 ```javascript 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 ```javascript 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 ```javascript 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 ```javascript 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 ```javascript // 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 ```javascript 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 ```javascript // .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.