Skip to content

Kapitel 10: Express Framework Einführung

🎯 Lernziele

In diesem Kapitel lernen Sie:

  • ✅ Was Express.js ist und warum man es verwendet
  • ✅ Express installieren und Projekt initialisieren
  • ✅ Express-Server erstellen und starten
  • ✅ Routing konfigurieren (GET, POST, etc.)
  • ✅ Middleware-Konzept verstehen
  • ✅ Statische Ressourcen bereitstellen
  • ✅ Express vs. native http-Modul

10.1 Was ist Express?

📖 Einfache Definition

Express.js ist ein minmalistisches Web-Framework für Node.js, das die Erstellung von Webservern und APIs drastisch vereinfacht.

🎨 Visuelle Erklärung

Ohne Express (Native http):
┌─────────────────────────────────┐
│  Viele if-else für Routing     │
│  Manuelle Header-Setzung      │
│  Komplexe Middleware-Logik    │
│  (Viel Boilerplate-Code!)     │
└─────────────────────────────────┘

Mit Express:
┌─────────────────────────────────┐
│  Einfache Routing-API         │
│  Automatische Header          │
│  Einfache Middleware          │
│  (Weniger Code, mehr Leistung!) │
└─────────────────────────────────┘

💡 Vorteile von Express

VorteilBeschreibung
EinfachWeniger Code für gleiche Funktionalität
FlexibelUnzählige Middleware verfügbar
PerformantMinimaler Overhead
BeliebtÜber 20 Millionen Downloads/Woche

🌟 Bekannte Unternehmen

  • Uber - Ride-sharing API
  • PayPal - Zahlungsabwicklung
  • Myntra - E-Commerce-Plattform

10.2 Installation & Initialisierung

📦 Express installieren

bash
# Neues Projekt erstellen
mkdir mein-express-projekt
cd mein-express-projekt

# npm-Projekt initialisieren
npm init -y

# Express installieren
npm install express

📄 package.json nach Installation

json
{
  "name": "mein-express-projekt",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  }
}

10.3 Kernfunktionen

🚀 Server erstellen und starten

index.js:

javascript
const express = require('express');
const app = express();
const port = 3000;

// Route definieren
app.get('/', (req, res) => {
  res.send('🎉 Hallo von Express-Server!');
});

// Server starten
app.listen(port, () => {
  console.log(`🚀 Express-Server läuft auf http://localhost:${port}`);
});

▶️ Server starten

bash
# Produktion
npm start

# Entwicklung (mit Nodemon)
npm run dev

🗺️ Routing konfigurieren

Einfache Routen

javascript
const express = require('express');
const app = express();

// GET-Route
app.get('/', (req, res) => {
  res.send('🏠 Startseite');
});

// POST-Route
app.post('/api/users', (req, res) => {
  res.send('✅ Nutzer erstellt');
});

// PUT-Route
app.put('/api/users/:id', (req, res) => {
  res.send(`🔄 Nutzer ${req.params.id} aktualisiert`);
});

// DELETE-Route
app.delete('/api/users/:id', (req, res) => {
  res.send(`🗑️ Nutzer ${req.params.id} gelöscht`);
});

// Alle Methoden (catch-all)
app.all('/test', (req, res) => {
  res.send(`Methode: ${req.method}`);
});

app.listen(3000);

Route mit Pfadparametern

javascript
// Route mit Parameter: /api/users/123
app.get('/api/users/:id', (req, res) => {
  const userId = req.params.id;
  res.send(`Nutzer-ID: ${userId}`);
});

// Mehrere Parameter: /api/users/123/posts/456
app.get('/api/users/:userId/posts/:postId', (req, res) => {
  const { userId, postId } = req.params;
  res.send(`Nutzer: ${userId}, Post: ${postId}`);
});

🧩 Middleware (Wichtig!)

MiddleWare = Funktionen, die zwischen Request und Response ausgeführt werden.

Visuelle Erklärung

Client-Anfrage (Request)

┌──────────────────────┐
│  Middleware 1         │ → loggingMiddleware()
└──────────────────────┘

┌──────────────────────┐
│  Middleware 2         │ → authMiddleware()
└──────────────────────┘

┌──────────────────────┐
│  Route-Handler       │ → app.get('/', ...)
└──────────────────────┘

Antwort (Response)

Eigene Middleware erstellen

javascript
const express = require('express');
const app = express();

// Eigene Middleware-Funktion
function loggingMiddleware(req, res, next) {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
  
  // WICHTIG: next() aufrufen, um zur nächsten Middleware/Route zu gelangen!
  next();
}

// Middleware global anwenden (für ALLE Routen)
app.use(loggingMiddleware);

// Route
app.get('/', (req, res) => {
  res.send('Startseite (mit Logging)');
});

app.listen(3000);

Ausgabe:

2024-01-15T10:30:00.000Z - GET /
2024-01-15T10:30:05.000Z - GET /about

Vordefinierte Middleware

javascript
const express = require('express');
const app = express();

// JSON-Body parsen (für POST/PUT)
app.use(express.json());

// URL-encoded Body parsen
app.use(express.urlencoded({ extended: true }));

// Statische Dateien servieren
app.use(express.static('public'));

// CORS aktivieren
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  next();
});

app.listen(3000);

📁 Statische Ressourcen bereitstellen

javascript
const express = require('express');
const app = express();

// Statische Dateien aus "public"-Ordner servieren
app.use(express.static('public'));

// Beispiel:
// public/
//   ├── index.html
//   ├── style.css
//   └── script.js

// Aufruf:
// http://localhost:3000/ → public/index.html
// http://localhost:3000/style.css → public/style.css

app.listen(3000, () => {
  console.log('📂 Statische Dateien aus ./public werden serviert');
});

Mehrere Statische Ordner

javascript
// Mehrere Ordner für statische Dateien
app.use(express.static('public'));
app.use(express.static('uploads'));
app.use('/bilder', express.static('bilder')); 
// → http://localhost:3000/bilder/logo.png

10.4 Praxisbeispiele

🛠️ Fallstudie 1: API-Server mit Express erstellen

server.js:

javascript
const express = require('express');
const app = express();
const port = 3000;

// Middleware
app.use(express.json()); // JSON-Body parsen
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

// "Datenbank" (Array)
let users = [
  { id: 1, name: 'Max', email: 'max@example.com' },
  { id: 2, name: 'Anna', email: 'anna@example.com' }
];

// ROUTES

// 1. Alle Nutzer abrufen (GET)
app.get('/api/users', (req, res) => {
  res.json({ success: true, data: users });
});

// 2. Einzelnen Nutzer abrufen (GET)
app.get('/api/users/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const user = users.find(u => u.id === id);
  
  if (!user) {
    return res.status(404).json({ success: false, error: 'Nutzer nicht gefunden' });
  }
  
  res.json({ success: true, data: user });
});

// 3. Nutzer erstellen (POST)
app.post('/api/users', (req, res) => {
  const { name, email } = req.body;
  
  if (!name || !email) {
    return res.status(400).json({ success: false, error: 'Name und Email erforderlich' });
  }
  
  const newUser = {
    id: users.length + 1,
    name,
    email
  };
  
  users.push(newUser);
  
  res.status(201).json({ success: true, data: newUser });
});

// 4. Nutzer aktualisieren (PUT)
app.put('/api/users/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const { name, email } = req.body;
  
  const userIndex = users.findIndex(u => u.id === id);
  
  if (userIndex === -1) {
    return res.status(404).json({ success: false, error: 'Nutzer nicht gefunden' });
  }
  
  users[userIndex] = { id, name, email };
  
  res.json({ success: true, data: users[userIndex] });
});

// 5. Nutzer löschen (DELETE)
app.delete('/api/users/:id', (req, res) => {
  const id = parseInt(req.params.id);
  const userIndex = users.findIndex(u => u.id === id);
  
  if (userIndex === -1) {
    return res.status(404).json({ success: false, error: 'Nutzer nicht gefunden' });
  }
  
  users.splice(userIndex, 1);
  
  res.json({ success: true, message: 'Nutzer gelöscht' });
});

// Server starten
app.listen(port, () => {
  console.log(`🚀 API-Server läuft auf http://localhost:${port}`);
  console.log('\nVerfügbare Endpunkte:');
  console.log('  GET    /api/users');
  console.log('  GET    /api/users/:id');
  console.log('  POST   /api/users');
  console.log('  PUT    /api/users/:id');
  console.log('  DELETE /api/users/:id');
});

Testen mit curl

bash
# Alle Nutzer abrufen
curl http://localhost:3000/api/users

# Einzelnen Nutzer abrufen
curl http://localhost:3000/api/users/1

# Nutzer erstellen
curl -X POST http://localhost:3000/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Clara","email":"clara@example.com"}'

# Nutzer aktualisieren
curl -X PUT http://localhost:3000/api/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name":"Max Mustermann","email":"max.neu@example.com"}'

# Nutzer löschen
curl -X DELETE http://localhost:3000/api/users/2

📂 Fallstudie 2: Statische Webseite mit Express

Projektstruktur:

meine-webseite/
├── server.js
├── public/
│   ├── index.html
│   ├── about.html
│   ├── css/
│   │   └── style.css
│   └── js/
│       └── script.js

server.js:

javascript
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;

// Statische Dateien servieren
app.use(express.static(path.join(__dirname, 'public')));

// Fallback: Wenn Route nicht gefunden → 404
app.use((req, res) => {
  res.status(404).sendFile(path.join(__dirname, 'public', '404.html'));
});

app.listen(port, () => {
  console.log(`🚀 Webserver läuft auf http://localhost:${port}`);
  console.log('📂 Statische Dateien aus ./public werden serviert');
});

public/index.html:

html
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Meine Webseite</title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>🏠 Willkommen!</h1>
  <p>Diese Webseite wird mit Express serviert.</p>
  <a href="/about.html">Über uns</a>
  <script src="/js/script.js"></script>
</body>
</html>

10.5 Vergleich

AspektNative httpExpress
RoutingManuell mit if/elseapp.get(), app.post(), etc.
MiddlewareSchwer zu implementierenEinfach mit app.use()
Body-ParsingManuell (req.on('data'))Automatisch (express.json())
Statische DateienManuell mit fs.createReadStream()express.static()
Code-MengeVielWeniger

📝 Code-Vergleich

Mit nativem http:

javascript
const http = require('http');
const fs = require('fs');
const url = require('url');

const server = http.createServer((req, res) => {
  const parsedUrl = url.parse(req.url);
  
  if (req.method === 'GET' && parsedUrl.pathname === '/') {
    fs.readFile('index.html', (err, data) => {
      if (err) {
        res.writeHead(500);
        res.end('Serverfehler');
      } else {
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.end(data);
      }
    });
  } else if (req.method === 'POST' && parsedUrl.pathname === '/api/data') {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => {
      const data = JSON.parse(body);
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ success: true, data }));
    });
  } else {
    res.writeHead(404);
    res.end('404 - Nicht gefunden');
  }
});

server.listen(3000);

Mit Express:

javascript
const express = require('express');
const app = express();

app.use(express.static('public'));
app.use(express.json());

app.get('/', (req, res) => {
  res.sendFile('index.html', { root: '.' });
});

app.post('/api/data', (req, res) => {
  res.json({ success: true, data: req.body });
});

app.use((req, res) => {
  res.status(404).send('404 - Nicht gefunden');
});

app.listen(3000);

Ergebnis: Express benötigt weniger Code und ist besser lesbar!


📝 Zusammenfassung

In diesem Kapitel haben Sie gelernt:

  • ✅ Express ist ein minimalistisches Web-Framework für Node.js
  • ✅ Express installieren (npm install express)
  • ✅ Express-Server erstellen und konfigurieren
  • ✅ Routing mit app.get(), app.post(), etc.
  • ✅ Middleware-Konzept und app.use()
  • ✅ Statische Dateien mit express.static() servieren
  • ✅ Express vs. native http (Express ist viel einfacher!)

🎯 Nächste Schritte

Im nächsten Kapitel werden wir:

  • Grundlegende Praxisprojekte durchführen
  • Log-Tool erstellen (FS-Modul)
  • Statischen Webserver erstellen
  • Einfache API-Schnittstellen entwickeln

📚 Weiterführende Ressourcen


🎉 Kapitel 10 abgeschlossen! Weiter zu Kapitel 11: Grundlegende Praxis

Frei für alle Anfänger