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
This commit is contained in:
+291
-214
@@ -8,277 +8,354 @@ footer: "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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
: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>
|
||||
|
||||
<!-- _class: invert -->
|
||||
<!-- _header: '' -->
|
||||
<!-- _backgroundColor: #000 -->
|
||||
<!-- _class: lead -->
|
||||
|
||||
# Web Engineering
|
||||
|
||||
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
|
||||
|
||||
**Sommersemester 2026** · Sitzung 4 — Node.js: Scripting, Running and Building
|
||||
# Kapitel 3 — Node.js Basics
|
||||
## JavaScript außerhalb des Browsers
|
||||
|
||||
---
|
||||
|
||||
# Ressourcen zum Selbstlernen
|
||||
# Was ist Node.js?
|
||||
|
||||
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
|
||||
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
|
||||
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
|
||||
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
|
||||
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
|
||||
**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.
|
||||
|
||||
---
|
||||
|
||||
# Inhalt
|
||||
# Warum Node?
|
||||
|
||||
1. Node.js: was und warum
|
||||
2. `node --check`, `node -e` (One-Liner)
|
||||
3. Module: `require` / `import`, `__dirname` / `__filename`
|
||||
4. HTTP-Server (built-in)
|
||||
5. `fs` — Dateien lesen / schreiben
|
||||
6. `package.json` — Aufbau und Lifecycle
|
||||
7. npm Scripts
|
||||
8. Module exportieren
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: invert -->
|
||||
<!-- _backgroundColor: #000 -->
|
||||
# Node Versions-Manager
|
||||
|
||||
# Node.js – Scripting, Running and Building
|
||||
**fnm** (oder `nvm`, `volta`) — pro Projekt Node-Version.
|
||||
|
||||
---
|
||||
```sh
|
||||
# Installieren (macOS/Linux)
|
||||
brew install fnm # oder curl-script
|
||||
|
||||
# Node.js – Was ist das?
|
||||
# Aktuelle LTS
|
||||
fnm install --lts
|
||||
fnm use lts-latest # 24.x
|
||||
|
||||
- JavaScript Runtime (V8 Engine)
|
||||
- Server-side JavaScript
|
||||
- npm Package Manager
|
||||
- Ideal für: APIs, CLI Tools, Automation
|
||||
|
||||
---
|
||||
|
||||
<!-- _header: '' -->
|
||||
<!-- _footer: '' -->
|
||||
|
||||

|
||||
|
||||
|
||||
---
|
||||
|
||||
# node --check und node -e
|
||||
|
||||
```bash
|
||||
# Syntax check only
|
||||
node --check script.js
|
||||
|
||||
# One-liner
|
||||
node -e "console.log('Hallo Welt')"
|
||||
# Pro Projekt
|
||||
echo "24" > .nvmrc
|
||||
fnm use # liest .nvmrc
|
||||
```
|
||||
|
||||
**Aktuell:** Node 24 LTS.
|
||||
|
||||
---
|
||||
|
||||
# node -e Beispiele
|
||||
# Projekt initialisieren
|
||||
|
||||
```bash
|
||||
# String
|
||||
node -e "console.log('Hello ' + process.argv[2])" Welt
|
||||
```sh
|
||||
mkdir mein-projekt && cd mein-projekt
|
||||
npm init -y # erzeugt package.json
|
||||
|
||||
# File reading (ESM via --input-type)
|
||||
node --input-type=module -e \
|
||||
"import { readFileSync } from 'node:fs'; \
|
||||
console.log(readFileSync('data.json', 'utf8'))"
|
||||
# Abhängigkeiten installieren
|
||||
npm install express # → dependencies
|
||||
npm install -D vitest # → devDependencies (nur dev)
|
||||
|
||||
# JSON parsen
|
||||
node -e "console.log(JSON.parse(process.argv[1]))" '{"a":1}'
|
||||
# Skripte ausführen
|
||||
npm run start
|
||||
npm test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Module laden – ESM (modern)
|
||||
|
||||
`"type": "module"` in `package.json` einschalten.
|
||||
|
||||
```javascript
|
||||
// Eigene Datei (Endung .js erforderlich!)
|
||||
import { add, greet } from "./utils.js";
|
||||
|
||||
// npm Modul (default + named import)
|
||||
import express from "express";
|
||||
import { Router } from "express";
|
||||
|
||||
// Built-in (mit "node:"-Präfix)
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
```
|
||||
|
||||
<small>**Legacy CJS:** `const express = require("express")` — funktioniert noch, aber ESM ist heute Standard.</small>
|
||||
`-y` = alle Defaults akzeptieren.
|
||||
|
||||
---
|
||||
|
||||
# Pfad-Auflösung in ESM
|
||||
|
||||
```javascript
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, join } from "node:path";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const configPath = join(__dirname, "..", "config.json");
|
||||
```
|
||||
|
||||
<small>In ESM gibt es **kein** automatisches `__dirname` / `__filename` (anders als CJS). Über `import.meta.url` rekonstruieren.</small>
|
||||
|
||||
---
|
||||
|
||||
# HTTP Server mit Node.js (Built-in)
|
||||
|
||||
**ESM** (modern, `"type": "module"` in `package.json`):
|
||||
```javascript
|
||||
import { createServer } from "node:http";
|
||||
|
||||
const server = createServer((req, res) => {
|
||||
res.writeHead(200, { "Content-Type": "text/html" });
|
||||
res.end("<h1>Hallo Welt!</h1>");
|
||||
});
|
||||
|
||||
server.listen(3000, () => {
|
||||
console.log("Server läuft auf Port 3000");
|
||||
});
|
||||
```
|
||||
|
||||
<small>**CommonJS** (legacy): `const http = require("http");` — funktioniert noch, aber neue Projekte nutzen ESM.</small>
|
||||
|
||||
---
|
||||
|
||||
# fs – Dateien lesen/schreiben
|
||||
|
||||
```javascript
|
||||
import { readFile, readFileSync, writeFile } from "node:fs";
|
||||
import { readFile as readFileAsync } from "node:fs/promises";
|
||||
|
||||
// Promise-API (empfohlen, modern)
|
||||
const data = await readFileAsync("data.json", "utf8");
|
||||
console.log(JSON.parse(data));
|
||||
|
||||
// Callback-API
|
||||
readFile("data.json", "utf8", (err, data) => {
|
||||
if (err) throw err;
|
||||
console.log(JSON.parse(data));
|
||||
});
|
||||
|
||||
// Sync (nur für Setup / Scripts)
|
||||
const content = readFileSync("data.json", "utf8");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# package.json – Das Herzstück
|
||||
# package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "mein-projekt",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"dev": "node --watch index.js",
|
||||
"test": "node --test"
|
||||
"dev": "node --watch src/server.js",
|
||||
"start": "node src/server.js",
|
||||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.18.0"
|
||||
"express": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.0"
|
||||
"vitest": "^2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`"type": "module"` aktiviert ESM.
|
||||
|
||||
---
|
||||
|
||||
# npm Scripts
|
||||
# ESM — modern
|
||||
|
||||
```bash
|
||||
# npm run <script>
|
||||
npm run start
|
||||
npm run dev
|
||||
```javascript
|
||||
// utils.js
|
||||
export function greet(name) {
|
||||
return `Hallo ${name}`;
|
||||
}
|
||||
|
||||
# Mit Argumenten
|
||||
npm run build -- --production
|
||||
export const VERSION = "1.0";
|
||||
|
||||
# Lifecycle scripts
|
||||
npm install → postinstall
|
||||
npm start → start (direkt)
|
||||
// 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.
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# 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);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Node.js Module – exports (ESM)
|
||||
# REST mit Express
|
||||
|
||||
```javascript
|
||||
// utils.js — named exports
|
||||
export const add = (a, b) => a + b;
|
||||
export const greet = (name) => `Hallo ${name}!`;
|
||||
const users = [{ id: 1, name: 'Ada' }];
|
||||
|
||||
// utils.js — default export
|
||||
export default {
|
||||
add,
|
||||
greet
|
||||
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/*
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: lead -->
|
||||
|
||||
# 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,
|
||||
};
|
||||
```
|
||||
|
||||
```javascript
|
||||
// nutzen
|
||||
import { add, greet } from "./utils.js"; // named
|
||||
import utils from "./utils.js"; // default
|
||||
import utils, { add } from "./utils.js"; // beides
|
||||
```
|
||||
**Niemals** API-Keys ins Repo committen.
|
||||
|
||||
<small>**Legacy CJS:** `module.exports = { add, greet }` + `const { add } = require("./utils")`.</small>
|
||||
---
|
||||
|
||||
<!-- _class: aufgabe -->
|
||||
|
||||
# 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.
|
||||
|
||||
Reference in New Issue
Block a user