Appearance
Kapitel 14: Fortgeschrittene Techniken
🎯 Lernziele
In diesem Kapitel lernen Sie:
- ✅ Umgebungsvariablen verwalten (
.env) - ✅ Fortgeschrittene Fehlerbehandlung (Global, Asynchron)
- ✅ Middleware entwickeln (Logging, Authentifizierung)
- ✅ Performance-Optimierung (Blocking vermeiden, Event Loop)
- ✅ Andere Frameworks kennenlernen (Koa, Nest.js)
14.1 Umgebungsvariablen
📖 Wozu Umgebungsvariablen?
Problem:
javascript
// ❌ Schlecht: Passwort im Code!
const dbPassword = 'meinPasswort123'; // Gefährlich!Lösung:
javascript
// ✅ Gut: Passwort aus Umgebungsvariable
const dbPassword = process.env.DB_PASSWORD; // Sicher!📦 dotenv installieren
bash
npm install dotenv📄 .env-Datei erstellen
.env:
env
# Datenbank
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=meinPasswort
DB_NAME=meine_datenbank
# Server
PORT=3000
NODE_ENV=development
# API-Keys
API_KEY=mein-api-key⚠️ Wichtig:
.envNIEMALS in Git einchecken!.gitignoreerstellen und.envhinzufügen
📥 dotenv verwenden
server.js:
javascript
require('dotenv').config(); // .env laden
const express = require('express');
const app = express();
const port = process.env.PORT || 3000; // Aus .env oder Standard 3000
// Datenbank-Verbindung (Passwort aus .env)
const dbPassword = process.env.DB_PASSWORD;
app.get('/', (req, res) => {
res.send(`Server läuft auf Port ${port}`);
});
app.listen(port, () => {
console.log(`🚀 Server läuft auf http://localhost:${port}`);
console.log(`Umgebung: ${process.env.NODE_ENV}`);
});🔍 process.env untersuchen
javascript
// Alle Umgebungsvariablen anzeigen
console.log(process.env);
// Einzelne Variable abrufen
console.log(process.env.DB_HOST); // 'localhost'
console.log(process.env.PORT); // '3000'
console.log(process.env.NICHT_VERHANDEN); // undefined📂 .env-Dateien für verschiedene Umgebungen
mein-projekt/
├── .env # Standard (Alle)
├── .env.development # Nur Entwicklung
├── .env.production # Nur Produktion
└── .env.test # Nur Testsdotenv mit spezifischer Datei laden:
javascript
require('dotenv').config({ path: '.env.production' });14.2 Fortgeschrittene Fehlerbehandlung
🔥 Globale Fehlerbehandlung
Synchroner Code
javascript
// ❌ Schlecht: Fehler wird nicht behandelt
function teilen(a, b) {
return a / b; // Wenn b = 0 → Fehler!
}
// ✅ Gut: Try/Catch verwenden
function teilen(a, b) {
try {
if (b === 0) {
throw new Error('Division durch Null ist nicht erlaubt!');
}
return a / b;
} catch (err) {
console.error('Fehler:', err.message);
return null;
}
}Asynchroner Code (Promises)
javascript
// ❌ Schlecht: Fehler wird ignoriert
fetchDaten().then(daten => {
console.log(daten);
});
// ✅ Gut: .catch() hinzufügen
fetchDaten()
.then(daten => {
console.log(daten);
})
.catch(err => {
console.error('Fehler beim Abrufen der Daten:', err.message);
});Asynchroner Code (async/await)
javascript
// ❌ Schlecht: Fehler wird nicht behandelt
async function datenAbrufen() {
const daten = await fetchDaten();
console.log(daten);
}
// ✅ Gut: try/catch verwenden
async function datenAbrufen() {
try {
const daten = await fetchDaten();
console.log(daten);
} catch (err) {
console.error('Fehler beim Abrufen der Daten:', err.message);
}
}🌐 Globale Fehlerbehandlung (Uncaught Exceptions)
javascript
// Unbehandelte Promise-Ablehnungen abfangen
process.on('unhandledRejection', (reason, promise) => {
console.error('Unbehandelte Promise-Ablehnung:', reason);
// Hier: Fehler loggen, Server neu starten, etc.
});
// Unbehandelte Ausnahmen abfangen
process.on('uncaughtException', (err) => {
console.error('Unbehandelte Ausnahme:', err);
// Hier: Server ordnungsgemäß herunterfahren
process.exit(1); // Server beenden
});🧩 Fehler in Express-Middleware
javascript
const express = require('express');
const app = express();
// Route mit Fehler
app.get('/api/daten', async (req, res, next) => {
try {
const daten = await datenbankAbfrage();
res.json(daten);
} catch (err) {
next(err); // Fehler an Fehler-Middleware weitergeben
}
});
// Fehler-Middleware (Muss 4 Parameter haben!)
app.use((err, req, res, next) => {
console.error('Fehler:', err.stack);
res.status(500).json({
erfolg: false,
fehler: err.message
});
});
app.listen(3000);14.3 Middle ware entwickeln
📦 Logging-Middleware
javascript
// middleware/logger.js
function loggerMiddleware(req, res, next) {
const startZeit = Date.now();
// Wenn Antwort gesendet wird
res.on('finish', () => {
const dauer = Date.now() - startZeit;
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url} ${res.statusCode} ${dauer}ms`);
});
next(); // Zur nächsten Middleware weitergehen
}
module.exports = loggerMiddleware;Verwendung:
javascript
const express = require('express');
const loggerMiddleware = require('./middleware/logger');
const app = express();
// Middleware global anwenden
app.use(loggerMiddleware);
app.get('/', (req, res) => {
res.send('Startseite');
});
app.listen(3000);Ausgabe:
[2024-01-15T10:30:00.000Z] GET / 200 5ms
[2024-01-15T10:30:05.000Z] GET /api/daten 200 120ms🔐 Authentifizierungs-Middleware
javascript
// middleware/auth.js
function authMiddleware(req, res, next) {
// Token aus Header abrufen
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ fehler: 'Kein Token bereitgestellt' });
}
// Token überprüfen (vereinfacht)
if (token !== 'mein-geheimer-token') {
return res.status(403).json({ fehler: 'Ungültiger Token' });
}
// Benutzerinformationen an Request anhängen
req.benutzer = { id: 1, name: 'Max' };
next(); // Weiter zur Route
}
module.exports = authMiddleware;Verwendung:
javascript
const express = require('express');
const authMiddleware = require('./middleware/auth');
const app = express();
// Geschützte Route
app.get('/api/profil', authMiddleware, (req, res) => {
res.json({
nachricht: 'Profil-Daten',
benutzer: req.benutzer
});
});
app.listen(3000);Testen:
bash
# Ohne Token → 401 Fehler
curl http://localhost:3000/api/profil
# Mit Token → 200 Erfolg
curl -H "Authorization: mein-geheimer-token" http://localhost:3000/api/profil14.4 Performance-Optimierung
⚠️ Blocking vermeiden
❌ Schlecht: Synchroner Code blockiert Event Loop
javascript
// Blockiert den Event Loop!
const daten = fs.readFileSync('große-datei.txt'); // ❌
console.log('Dies wird erst ACHHER ausgeführt!');✅ Gut: Asynchroner Code
javascript
// Blockiert nicht!
fs.readFile('große-datei.txt', 'utf8', (err, daten) => {
if (err) throw err;
console.log('Datei gelesen');
});
console.log('Dies wird SOFORT ausgeführt!'); // ✅🔄 Event Loop verstehen
┌───────────────────────────┐
│ Event Loop │
└───────────────────────────┘
↓ ↓ ↓
┌──────────┐ ┌──────┐ ┌────────┐
│ Timers │ │ I/O │ │ Close │
│ (setTimeout) │
└──────────┘ └──────┘ └────────┘Regel: Lange dauernde Operationen (z.B. große Dateien lesen, komplexe Berechnungen) blockieren den Event Loop!
⚡ Performance-Tipps
| Tipp | Beschreibung |
|---|---|
| Asynchron bleiben | readFileSync vermeiden |
| Streaming verwenden | Bei großen Dateien fs.createReadStream() |
| Caching | Ergebnisse speichern, um erneute Berechnungen zu vermeiden |
| Cluster-Modul | Mehrere CPU-Kerne nutzen |
| Load Balancing | Last verteilen (z.B. mit NGINX) |
📊 Beispiel: Streaming für große Dateien
javascript
const fs = require('fs');
const http = require('http');
const path = require('path');
const server = http.createServer((req, res) => {
if (req.url === '/große-datei') {
// ❌ Schlecht: Alles auf einmal lesen
// const daten = fs.readFileSync('große-datei.txt');
// res.end(daten);
// ✅ Gut: Streaming verwenden
const readStream = fs.createReadStream('große-datei.txt');
readStream.pipe(res); // Direkt an Antwort senden
}
});
server.listen(3000);14.5 Andere Frameworks
🌿 Koa.js
Was ist Koa?
- Von den Machern von Express
- Verwendet async/await (Keine Callbacks!)
- Sehr dünn und modern
Installation:
bash
npm install koaBeispiel:
javascript
const Koa = require('koa');
const app = new Koa();
// Middleware
app.use(async (ctx) => {
ctx.body = 'Hallo von Koa!';
});
app.listen(3000);🏗️ Nest.js
Was ist Nest.js?
- Fortgeschrittenes Framework
- Verwendet TypeScript
- Ähnlich wie Angular (für Backend)
Installation:
bash
npm i -g @nestjs/cli
nest new mein-projektBeispiel:
typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();📊 Vergleich
| Framework | Vorteile | Nachteile |
|---|---|---|
| Express | Einfach, beliebt | Veraltet (Callbacks) |
| Koa | Modern, async/await | Kleinere Community |
| Nest.js | TypeScript, strukturiert | Komplex für Anfänger |
📝 Zusammenfassung
In diesem Kapitel haben Sie gelernt:
- ✅ Umgebungsvariablen mit
dotenvverwalten - ✅ Fortgeschrittene Fehlerbehandlung (Global, Asynchron)
- ✅ Middleware entwickeln (Logging, Authentifizierung)
- ✅ Performance-Optimierung (Blocking vermeiden, Streaming)
- ✅ Andere Frameworks (Koa, Nest.js)
🎯 Nächste Schritte
Im nächsten Kapitel werden wir:
- Häufige Interviewfragen zu Node.js vorbereiten
- Grundlegende Konzepte wiederholen
- Fortgeschrittene Themen üben
📚 Weiterführende Ressourcen
- dotenv Dokumentation
- Node.js Performance-Best Practices
- Koa.js Offizielle Webseite
- Nest.js Dokumentation
🎉 Kapitel 14 abgeschlossen! Weiter zu Kapitel 15: Interviewfragen
