Node.js Framework

Express

Express ist das minimale, unvoreingenommene Node.js Web-Framework. Eine Route, eine Funktion und eine middleware Kette – das ist das gesamte mentale Modell, und dennoch treibt es einen riesigen Teil des Webs an.

beginner16 min readUpdated 16. Sept. 2026
server.js
js
// server.js
import express from "express";

const app = express();
app.use(express.json());

app.get("/users/:id", async (req, res, next) => {
  try {
    const user = await db.user.findById(req.params.id);
    if (!user) return res.status(404).json({ error: "not_found" });
    res.json(user);
  } catch (err) {
    next(err);
  }
});

app.listen(3000);
Veröffentlicht
2010
Läuft auf
Node.js
Stil
Minimal, unvoreingenommen
Kernidee
middleware Kette
Sprache
JavaScript / TypeScript
Version
5.x

Warum es wichtig ist

Warum Express immer noch überall ist

Routing ohne unnötigen Ballast

Definiere Endpunkte mit app.get, app.post und Co. Pfade können statisch, parametrisiert oder über Muster definiert werden, und Handler bleiben einfache Funktionen.

middleware für alles

Authentifizierung, Logging, Parsing und Validierung sind einfach Funktionen in einer Kette. Setze kleine Bausteine zusammen, anstatt ein riesiges Framework zu konfigurieren.

Ein enormes Ökosystem

Tausende von middleware Paketen und jahrelange Erfahrung bedeuten, dass es für fast jedes Problem bereits eine kleine, gut getestete Lösung gibt.

Das Gesamtbild

Die drei Kernideen hinter Express

Eine Route matcht eine URL, ein Handler empfängt Request und Response, und middleware umschließt alles dazwischen.

Routing

Match

Eine Methode und ein Pfad wählen den auszuführenden Handler aus. Routen können in Routern gruppiert und unter einem Präfix eingehängt werden.

middleware

Compose

Funktionen empfangen (req, res, next) und beenden entweder die Response oder geben die Kontrolle an die nächste Stelle in der Kette weiter.

Request & Response

Exchange

Dünne Wrapper um die HTTP-Objekte von Node — Input lesen, Status und Header setzen und einen Body senden.

HTML5 auf einen Blick

Was man tatsächlich bekommt

Routes

app.get("/posts/:id") matcht eine URL und führt einen Handler aus.

middleware

app.use(fn) wird vor oder nach Routen in der Reihenfolge der Registrierung ausgeführt.

req und res

Params, Query und Body lesen; Status setzen und JSON oder Dateien senden.

Router

express.Router() hält große Apps modular und einhängbar.

Error middleware

Eine Funktion mit vier Argumenten zentralisiert Fehler-Responses.

Security middleware

helmet, cors und Rate-Limits lassen sich als Einzeiler integrieren.

Eine kurze Geschichte

Vom Sinatra-inspirierten Spielzeug zum Webstandard

  1. 2010

    Express wird geboren

    TJ Holowaychuk veröffentlicht ein kleines Framework, inspiriert von Rubys Sinatra.

    10
  2. 2011

    Connect middleware

    Express übernimmt das middleware Modell von Connect, welches die API über Jahre hinweg definiert.

    11
  3. 2014

    Express 4

    Der Router wird neu geschrieben und middleware wird in separate Pakete ausgelagert.

    14
  4. 2016

    Die Ära der offenen Governance

    Die Betreuung durch IBM und StrongLoop hält Express während des Wachstums von Node aktuell.

    16
  5. 2024

    Express 5

    Ein lang erwartetes Major-Release bringt async Fehlerbehandlung und eine moderne Basis.

    24

Der vollständige Leitfaden

Express: Alles was Sie wissen müssen

Was ist Express?

Express ist ein minimales Web-Framework für Node.js. Es schreibt dir weder deine Ordnerstruktur, deine Datenbank noch deine Architektur vor. Es bietet dir drei Dinge und hält sich ansonsten zurück: eine Möglichkeit zum URL-Matching, ein Request- und ein Response-Objekt sowie eine middleware-Kette, die diese miteinander verbindet.

Genau diese Zurückhaltung ist der Kernpunkt. Express erschien im Jahr 2010, als das integrierte http-Modul von Node es erforderte, Routing und Body-Parsing manuell zu schreiben. Express reduzierte diese Aufgaben auf wenige Zeilen. Fünfzehn Jahre später ist es immer noch die Standardwahl für Node-APIs, und seine Konzepte wurden von fast jedem nachfolgenden Framework übernommen.

Wenn du Express verstehst, verstehst du die grundlegende Struktur von serverseitigem JavaScript.

Der Request-Response-Zyklus

Im Kern ist eine Express-App eine Funktion, die einen Request empfängt und eine Response sendet. Alles andere ist lediglich ein Komfort-Feature darauf.

import express from "express";

const app = express();

app.get("/", (req, res) => {
  res.send("Hello, world");
});

Das req-Objekt kapselt die eingehende Nachricht von Node.js: req.params, req.query, req.body und req.headers liefern Ihnen den Input. Das res-Objekt kapselt die ausgehende Nachricht: res.status(), res.json(), res.send() und res.set() formen den Output. Ein Handler beendet den Request, indem er eine der res-Methoden aufruft.

Routing

Eine Route besteht aus einer Methode, einem Pfad und einem oder mehreren Handlern. Pfade können statisch sein, mit :name parametrisiert werden oder über Muster (Patterns) abgeglichen werden.

app.get("/posts", listPosts);
app.get("/posts/:id", getPost);
app.post("/posts", createPost);
app.put("/posts/:id", replacePost);
app.patch("/posts/:id", updatePost);
app.delete("/posts/:id", deletePost);

Routenparameter werden in req.params übergeben und Query-Strings in req.query.

app.get("/posts/:id", (req, res) => {
  const { id } = req.params;          // "/posts/42" -> "42"
  const { fields } = req.query;       // "?fields=title" -> "title"
  res.json({ id, fields });
});

Sie können auch mehrere Handler an eine einzige Route übergeben. Diese werden nacheinander ausgeführt, bis einer die Antwort beendet. Auf diese Weise können Sie pro Route middleware für Aufgaben wie Validierung oder Autorisierung hinzufügen.

app.post("/posts", requireAuth, validatePost, createPost);

Middleware: Das eine Konzept, das man beherrschen muss

Middleware ist das Herzstück von Express. Es handelt sich dabei um jede Funktion, die (req, res, next) erhält und entweder die Antwort beendet oder next() aufruft, um fortzufahren.

function logger(req, res, next) {
  const start = Date.now();
  res.on("finish", () => {
    console.log(`${req.method} ${req.url} ${res.statusCode} ${Date.now() - start}ms`);
  });
  next();
}

app.use(logger);

Middleware wird in der Reihenfolge ausgeführt, in der sie registriert wurde. Diese eine Regel erklärt den Großteil des Express-Verhaltens: Registrieren Sie den JSON-Parser vor den Routen, die req.body lesen, registrieren Sie die Authentifizierung vor geschützten Routen und registrieren Sie den 404-Handler nach jeder Route.

Es gibt drei Arten, die man kennen sollte:

  • Application middlewareapp.use(fn) wird für jede Anfrage ausgeführt.
  • Router middlewarerouter.use(fn) wird nur für die Pfade dieses Routers ausgeführt.
  • Route middlewareapp.get(path, fn, handler) wird nur für diese spezifische Route ausgeführt.

Eine Middleware, die vier Argumente entgegennimmt, ist ein Error Handler und wird nur ausgeführt, wenn etwas next(err) aufruft.

Router halten große Apps übersichtlich

Wenn eine App wächst, wird eine einzelne Datei für alle Routen unhandlich. express.Router() ermöglicht es, zusammengehörige Routen zu gruppieren und sie unter einem Präfix zu mounten.

// routes/posts.js
import { Router } from "express";

const router = Router();

router.get("/", listPosts);
router.post("/", createPost);

export default router;
// app.js
import posts from "./routes/posts.js";

app.use("/api/v1/posts", posts);

Jetzt ist jede Datei für eine Ressource zuständig und das URL-Präfix wird an einer zentralen Stelle definiert. Diese Struktur verhindert, dass Express-Projekte in einem unübersichtlichen Haufen von Endpunkten enden.

Fehlerbehandlung

Fehler sollten an einem zentralen Ort zusammenlaufen. Rufen Sie next(err) von überall aus auf, und Express springt direkt zum ersten Error-Handler mit vier Argumenten.

app.get("/users/:id", async (req, res, next) => {
  try {
    const user = await db.user.findById(req.params.id);
    if (!user) return res.status(404).json({ error: "not_found" });
    res.json(user);
  } catch (err) {
    next(err);
  }
});
app.use((err, req, res, next) => {
  console.error(err);
  res.status(err.status ?? 500).json({
    error: err.code ?? "internal_error",
    message: err.message,
  });
});

Express 5 leitet rejectete Promises automatisch an den Error-Handler weiter, sodass async-Handler keinen Wrapper mehr benötigen. Dennoch macht die explizite Verwendung von try/catch die Absicht deutlich und hält den Code portabel. Registrieren Sie nach allen Routen einen 404-Handler, damit nicht zugeordnete Pfade einen ordnungsgemäßen JSON-Fehler anstelle der Standard-HTML-Seite von Express zurückgeben.

Den Request-Body auslesen

Express parst Request-Bodies standardmäßig nicht. Füge die integrierten Parser vor den Routen hinzu, die diese benötigen.

app.use(express.json());                        // application/json
app.use(express.urlencoded({ extended: true })); // form posts

Für Datei-Uploads solltest du multer verwenden. Für eine umfassendere Validierung kombiniere das Parsing mit einer Schema-Library wie Zod oder Joi und lehne ungültige Eingaben frühzeitig ab, noch bevor sie deine Handler erreichen.

Grundlagen für Sicherheit und Produktion

Express ist bewusst minimalistisch gehalten, sodass einige Einzeiler als middleware die wichtigsten Grundlagen abdecken:

import helmet from "helmet";
import cors from "cors";
import rateLimit from "express-rate-limit";

app.use(helmet());                 // sensible security headers
app.use(cors({ origin: "https://app.example.com" }));
app.use(rateLimit({ windowMs: 60_000, max: 100 }));

Deaktivieren Sie außerdem x-powered-by, halten Sie Abhängigkeiten aktuell, validieren und begrenzen Sie die Größe von Anfragen und vertrauen Sie niemals Benutzereingaben vom Client. Dies sind dieselben Herausforderungen, mit denen jedes Backend konfrontiert ist; Express bietet Ihnen lediglich einen kompakten, bewährten Ort, um diese zu handhaben.

Testing

Da Handler einfache Funktionen sind, lässt sich Express leicht testen. supertest bootet die App im selben Prozess und ermöglicht echte HTTP-Assertions, ohne einen Port öffnen zu müssen.

import request from "supertest";
import app from "../app.js";

test("GET /posts returns a list", async () => {
  const res = await request(app).get("/posts").expect(200);
  expect(Array.isArray(res.body)).toBe(true);
});

Trennen Sie die App-Definition (app.js) vom Server-Start (server.js), damit Tests die App importieren können, ohne dass diese auf Anfragen hört. Diese eine Trennung macht Integrationstests trivial.

Best Practices

  • Halten Sie Route-Handler schlank; verschieben Sie die Logik in Services und Data-Access-Layer.
  • Teilen Sie Routen nach Features mit express.Router() auf und mounten Sie diese unter einem Versions-Präfix.
  • Registrieren Sie middleware bewusst und in der richtigen Reihenfolge: zuerst Parser, dann Auth, dann Routen, dann 404 und schließlich Fehler.
  • Leiten Sie jeden Fehler mit next(err) weiter und formatieren Sie Antworten an einer zentralen Stelle.
  • Validieren und begrenzen Sie alle Eingaben, bevor sie die Business-Logik erreichen.
  • Nutzen Sie helmet, cors und Rate Limiting vom ersten Tag an.
  • Trennen Sie die App vom Server, damit die Tests schnell bleiben.

Häufige Fehler

  • express.json() vergessen und sich wundern, warum req.body undefined ist.
  • Abgelehnte Promises in async-Handlern unter Express 4 ignorieren.
  • Den 404- oder Error-Handler vor den Routen registrieren, die er abfangen soll.
  • Eine einzelne Routen-Datei auf hunderte von Zeilen anwachsen lassen.
  • Bei Fehlern 200 zurückgeben, anstatt die entsprechenden Status-Codes zu verwenden.
  • req.body ohne Validierung vertrauen.
  • res.send, res.json und res.end unvorhersehbar mischen.

Wie geht es weiter?

Express vermittelt die Konzepte von Request, Response und der middleware-Kette – Grundlagen, die du immer wieder verwenden wirst. Wenn du mehr Geschwindigkeit und integrierte Validierung suchst, lies als Nächstes den Fastify-Guide. Wenn du Struktur und Dependency Injection für ein großes Team benötigst, wechsle zu NestJS. Für Edge- und Serverless-Deployments bietet Hono den gleichen Stil auf einer Web-Standards-Runtime. Und falls dir das alles zu schnell ging, schau dir noch einmal die Node.js basics an, auf denen all dies aufbaut.

In der Praxis

Eine App, vier bewegliche Teile

Wechsle zwischen den Teilen, um zu sehen, wie sie zusammenpassen.

server.js
import express from "express";
import routes from "./routes.js";

const app = express();

app.use(express.json());
app.use("/api", routes);

app.listen(3000, () => console.log("http://localhost:3000"));

Handling von async Fehlern

Express 5 leitet rejected Promises automatisch weiter, aber explizites Handling ist immer noch klarer und funktioniert in jeder Version gleich.

Bevorzugt
router.get("/posts", async (req, res, next) => {
  try {
    const posts = await Post.find();
    res.json(posts);
  } catch (err) {
    next(err);
  }
});
Vermeiden
router.get("/posts", async (req, res) => {
  const posts = await Post.find();
  res.json(posts);
  // rejection is silently lost in Express 4
});

Reihenfolge der middleware

middleware wird in der Reihenfolge der Registrierung ausgeführt, daher müssen Parser und Auth vor den Routen eingehängt werden, die von ihnen abhängen.

Bevorzugt
app.use(express.json());
app.use(auth);
app.use("/api", routes);
app.use(notFound);
app.use(onError);
Vermeiden
app.use("/api", routes);
app.use(express.json());
app.use(auth);
// body is undefined inside routes

Abwägungen

Ist Express der richtige Standard?

Express optimiert auf Vertrautheit und Einfachheit. Kenne die Kosten, bevor du es skalierst.

Strengths

  • Keine Vorkenntnisse nötig

    Die API ist winzig, die Dokumentation exzellent und fast jeder Node-Entwickler kann eine Express-App vom ersten Tag an lesen.

  • Unübertroffenes Ökosystem

    Authentifizierung, Uploads, Sessions, Validierung und Logging verfügen alle über ausgereifte middleware mit jahrelangem Praxiseinsatz.

  • Du behältst die Kontrolle

    Es gibt keine versteckte Struktur. Du wählst das Ordnerlayout, die Datenbank und die Patterns, anstatt die Meinungen eines Frameworks zu übernehmen.

Trade-offs

  • Du baust die Konventionen selbst

    Ohne eine vereinbarte Struktur driften große Express-Apps oft in inkonsistente Handler ab. Ein klares Layout ist hier wichtiger als in opinionierten Frameworks.

  • Performance ist gut, aber nicht überragend

    Express ist für die meisten Dienste schnell genug, aber Fastify und natives Node können spürbar mehr Requests pro Sekunde verarbeiten.

  • Async Fehler werden leicht übersehen

    In Express 4 wird ein rejected Promise stillschweigend verworfen. Selbst in Version 5 halten try/catch oder next(err) Fehler sichtbar.

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, Express zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch Express — mit Quizzen und echtem Code, den Sie im Browser ausführen können.