Next.js vs. Express: Nur eines von beiden rendert
Express ist ein Server, auf dem Sie aufbauen. Next.js ist ein Rendering-Framework mit angeschlossenem Server. Die Wahl ist eigentlich eine Frage danach, wie viel Sie selbst schreiben wollen.
Diese beiden werden verglichen, weil beide Node sind und beide HTTP bedienen - und damit endet die Ähnlichkeit ungefähr. Express ist ein minimales HTTP-Framework, das Sie zusammensetzen. Next.js ist ein Rendering-Framework, das zufällig einen Server enthält.
Die Entscheidung ist eigentlich kein Vergleich. Es ist eine Frage danach, was Sie bauen.
| Express | Next.js | |
|---|---|---|
| Was Sie bekommen | Eine Request-Pipeline | Einen Render-Pfad |
| Routing | Was Sie schreiben | Dateisystem, mit Layouts |
| Rendering | Keines | Der ganze Zweck |
| Client-Bundling | Nicht seine Aufgabe | Eingebaut |
| Langlebige Verbindungen | Nativ | Umständlich bis unmöglich |
| Was Sie selbst zusammenbauen | Ein halbes Frontend | Ein halbes Backend |
Wenn Sie eine API bauen und sonst nichts
Nehmen Sie Express, oder Fastify, oder Hono. Next.js-Route-Handler gibt es und sie funktionieren, aber Sie nähmen ein Rendering-Framework, einen Build-Schritt, einen dateisystembasierten Router und eine React-Abhängigkeit in Kauf - für einen Dienst, der nichts rendert.
Konkret bleibt Express besser, wenn Ihre API Folgendes hat:
- Externe Konsumenten. Versionierte Routen, API-Schlüssel, dokumentierte Verträge.
- Eine eigene Middleware-Kette. Rate Limiting, Request-Validierung, eigene Authentifizierung, Logging, das Ihnen gehört.
- Irgendetwas Langlebiges. WebSockets, Server-Sent Events, Verbindungen, die einen Request überdauern.
- Deployment-Einschränkungen. Ein schlichter Node-Prozess ist einfacher zu betreiben auf Infrastruktur, die Meinungen hat.
Der Middleware-Punkt verdient mehr als einen Aufzählungspunkt, weil er spät
entdeckt wird. Eine Express-Anwendung ist eine Pipeline, die Sie
zusammensetzen: jeder Request durchläuft die Funktionen, die Sie registriert
haben, in der Reihenfolge, in der Sie sie registriert haben, und die ganze
Kette lässt sich durch das Lesen einer Datei nachvollziehen. Next.js hat auf
Anwendungsebene nichts Gleichwertiges. proxy.ts - die Konvention, die in 16
Middleware ersetzt hat - läuft auf einem Matcher, auf Requests, die Sie
vielleicht nicht gemeint haben, und
ist keine Request-Pipeline. Der Versuch, sie
als eine zu benutzen, ist der häufigste Weg, auf dem ein Team eine
Express-Gewohnheit in eine Codebasis trägt, die sie nicht tragen kann.
Wenn Sie Seiten rendern, bauen Sie es nicht selbst
Die Gegenrichtung ist stärker und weniger offensichtlich.
Teams, die mit Express beginnen und React obendrauf setzen, schreiben am Ende von Hand, was Next.js bereits entschieden hat: Routing, Code Splitting, serverseitiges Datenladen, Streaming, die Client-Bundle-Grenze, Bildhandling, Caching. Jedes davon ist eine Woche. Zusammen sind sie ein Framework - und es wird ein schlechteres, weil es ein Nebenprojekt ist statt das Produkt.
Wenn Ihre Anwendung Seiten hat, ist das Argument für Express das Argument dafür, ein eigenes Framework zu schreiben. Das ist gelegentlich richtig und meistens nicht.
Unterschätzt wird dabei nicht der einzelne Punkt auf dieser Liste. Unterschätzt wird, dass diese Entscheidungen einander bedingen. Code Splitting muss vom Routing wissen. Streaming muss von der Datenschicht wissen. Die Client-Grenze muss von beidem wissen. Ein Framework ist deshalb so viel wert, weil jemand diese Entscheidungen zueinander konsistent gemacht hat - und ein eigener Stack ist der Ort, an dem sie das langsam nicht mehr sind.
Wo Route Handler wirklich genügen
Für eine API, die nur Ihr eigenes Frontend nutzt, erledigen Next.js-Route-Handler die Aufgabe:
// app/api/products/route.ts
export async function GET(request: Request) {
const products = await db.product.findMany();
return Response.json(products);
}Ein Deployment, eine Codebasis, geteilte Typen zwischen API und den Komponenten, die sie aufrufen. Für die meisten Produktanwendungen ist das die richtige Menge Maschinerie.
Gut zu wissen: Für Daten, die Ihre eigenen Seiten brauchen, benötigen Sie oft gar keine Route. Eine Server Component kann direkt abfragen, und eine Server Action kann mutieren - der Umweg über die eigene HTTP-API ist eine Gewohnheit aus einer clientseitig gerenderten Architektur.
Wo Route Handler nicht mehr genügen
Drei Grenzen, in der Reihenfolge, in der Teams sie erreichen.
Die Verbindung muss offen bleiben. Ein Route Handler ist um einen Request herum gebaut, der endet. Server-Sent Events gehen über eine gestreamte Antwort; ein WebSocket nicht - und auf einem Serverless-Target überlebt beides die Lebensdauer der Funktion nicht. Alles mit dauerhafter Verbindung gehört in einen Prozess, den Sie kontrollieren.
Etwas muss nach Zeitplan passieren. Es gibt keinen Job-Runner. Ein Cron-Dienst, der einen authentifizierten Endpunkt aufruft, deckt die einfachen Fälle ab - und hört in dem Moment damit auf, in dem ein Job eine Retry-Policy, eine Dead-Letter-Queue oder mehr Zeit braucht, als das Ausführungslimit der Plattform erlaubt.
Die API hat Konsumenten, die nicht Sie sind. Versionierung, Deprecation, Rate Limits pro Client, eine Authentifizierung getrennt von der Session Ihres Frontends, und Dokumentation als Vertrag. Jedes davon ist in Route Handlern baubar, und jedes davon existiert bereits in dem Ökosystem, das Sie sonst gewählt hätten.
Die Anordnung, bei der die meisten Teams landen
Express - oder Fastify, oder ein Go-Dienst, oder Laravel - trägt die Geschäftslogik und die Jobs. Next.js trägt das Frontend. Sie sprechen über HTTP.
Das ist dieselbe Schlussfolgerung wie bei Next.js gegen Laravel, aus demselben Grund: Render-Pfad und Geschäftslogik sind verschiedene Probleme, und Frameworks sind jeweils in einem davon gut.
Der Preis ist real und gehört genannt: zwei Deployment-Targets, ein Vertrag dazwischen, den jemand pflegt, und Typen, die über eine Netzwerkgrenze hinweg synchron gehalten werden müssen, statt von einem Compiler geprüft zu werden. Teams, die diese Aufteilung übernehmen, ohne diesen Preis anzuerkennen, enden mit einem Frontend, das die Hälfte der API-Regeln nachbaut, um einen Roundtrip zu vermeiden.
Was Sie nicht tun sollten
Einen Custom-Express-Server vor Next.js. Es wird unterstützt und deaktiviert die automatische statische Optimierung für die Routen, die er bedient - also für das meiste, weswegen Sie gekommen sind. Wenn Sie einen Proxy brauchen, stellen Sie ihn vor beide Prozesse statt in einen von ihnen.
Eine Express-Middleware-Kette nach proxy.ts portieren. Die Konvention,
die Middleware in 16 ersetzt hat, läuft auf Node,
ist nicht konfigurierbar und läuft bei Requests,
die Sie nicht vorgesehen hatten. Sie ist für Routing-Entscheidungen da, nicht
für eine Request-Pipeline.
