Lernen Sie, wie Sie mit Next.js Route Handlers leistungsstarke API-Endpunkte erstellen. Dieser Leitfaden deckt alles ab, von der Grundeinrichtung bis hin zu fortgeschrittenen Techniken, mit praktischen Beispielen und Best Practices.
Next.js Route Handlers: Ein umfassender Leitfaden zur Erstellung von API-Endpunkten
Next.js hat die Art und Weise, wie wir Webanwendungen erstellen, mit seinen leistungsstarken Funktionen wie serverseitigem Rendern, statischer Seitengenerierung und jetzt auch Route Handlers revolutioniert. Route Handlers bieten eine flexible und effiziente Möglichkeit, API-Endpunkte direkt in Ihrer Next.js-Anwendung zu erstellen. Dieser Leitfaden untersucht das Konzept der Route Handlers, ihre Vorteile und wie man sie effektiv einsetzt, um robuste APIs zu erstellen.
Was sind Next.js Route Handlers?
Route Handlers sind Funktionen, die im app
-Verzeichnis eines Next.js-Projekts definiert sind und eingehende HTTP-Anfragen bearbeiten. Im Gegensatz zum älteren pages/api
-Ansatz (der API-Routen verwendet) bieten Route Handlers eine optimiertere und flexiblere Möglichkeit, API-Endpunkte neben Ihren React-Komponenten zu definieren. Sie sind im Wesentlichen serverlose Funktionen, die am Edge oder in Ihrer gewählten Serverumgebung ausgeführt werden.
Stellen Sie sich Route Handlers als die Backend-Logik Ihrer Next.js-Anwendung vor, die für die Verarbeitung von Anfragen, die Interaktion mit Datenbanken und die Rückgabe von Antworten verantwortlich ist.
Vorteile der Verwendung von Route Handlers
- Colocation: Route Handlers befinden sich direkt neben Ihren React-Komponenten im
app
-Verzeichnis, was eine bessere Organisation und Wartbarkeit des Codes fördert. - TypeScript-Unterstützung: Die integrierte TypeScript-Unterstützung gewährleistet Typsicherheit und eine verbesserte Entwicklererfahrung.
- Middleware-Integration: Einfache Integration von Middleware für Aufgaben wie Authentifizierung, Autorisierung und Anforderungsvalidierung.
- Streaming-Unterstützung: Route Handlers können Daten streamen, sodass Sie Antworten schrittweise senden können, was bei großen Datensätzen oder lang andauernden Prozessen von Vorteil ist.
- Edge Functions: Stellen Sie Route Handlers als Edge Functions bereit, um Antworten mit geringer Latenz näher an Ihren Benutzern zu erzielen und globale CDNs zu nutzen.
- Vereinfachtes API-Design: Route Handlers bieten eine saubere und intuitive API zur Handhabung von Anfragen und Antworten.
- Integration von Server Actions: Die enge Integration mit Server Actions ermöglicht eine nahtlose Kommunikation zwischen Ihren clientseitigen Komponenten und der serverseitigen Logik.
Einrichten Ihres Next.js-Projekts
Bevor Sie sich mit Route Handlers befassen, stellen Sie sicher, dass Sie ein Next.js-Projekt mit dem app
-Verzeichnis eingerichtet haben. Wenn Sie ein neues Projekt starten, verwenden Sie den folgenden Befehl:
npx create-next-app@latest my-nextjs-app
Wählen Sie während des Einrichtungsprozesses das app
-Verzeichnis, um das neue Routing-System zu aktivieren.
Erstellen Ihres ersten Route Handlers
Lassen Sie uns einen einfachen API-Endpunkt erstellen, der eine JSON-Antwort zurückgibt. Erstellen Sie ein neues Verzeichnis im app
-Verzeichnis, zum Beispiel /app/api/hello
. Erstellen Sie in diesem Verzeichnis eine Datei namens route.ts
(oder route.js
, wenn Sie TypeScript nicht verwenden).
Hier ist der Code für Ihren ersten Route Handler:
// app/api/hello/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
}
Erklärung:
import { NextResponse } from 'next/server';
: Importiert dasNextResponse
-Objekt, das zum Erstellen von API-Antworten verwendet wird.export async function GET(request: Request) { ... }
: Definiert eine asynchrone Funktion, die GET-Anfragen an den/api/hello
-Endpunkt behandelt. Derrequest
-Parameter bietet Zugriff auf das eingehende Anfrageobjekt.return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
: Erstellt eine JSON-Antwort mit einer Nachricht und gibt sie mitNextResponse.json()
zurück.
Jetzt können Sie auf diesen Endpunkt zugreifen, indem Sie in Ihrem Browser zu /api/hello
navigieren oder ein Tool wie curl
oder Postman
verwenden.
Umgang mit verschiedenen HTTP-Methoden
Route Handlers unterstützen verschiedene HTTP-Methoden wie GET, POST, PUT, DELETE, PATCH und OPTIONS. Sie können für jede Methode separate Funktionen in derselben route.ts
-Datei definieren.
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Logik zum Abrufen aller Benutzer aus der Datenbank
const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Beispieldaten
return NextResponse.json(users);
}
export async function POST(request: Request) {
const data = await request.json(); // Den Anfragekörper als JSON parsen
// Logik zum Erstellen eines neuen Benutzers in der Datenbank mit 'data'
const newUser = { id: 3, name: data.name, email: data.email }; // Beispiel
return NextResponse.json(newUser, { status: 201 }); // Den neuen Benutzer mit dem Statuscode 201 Created zurückgeben
}
Erklärung:
- Die
GET
-Funktion ruft eine Liste von Benutzern ab (hier simuliert) und gibt sie als JSON-Antwort zurück. - Die
POST
-Funktion parst den Anfragekörper als JSON, erstellt einen neuen Benutzer (simuliert) und gibt den neuen Benutzer mit dem Statuscode 201 Created zurück.
Zugriff auf Anfragedaten
Das request
-Objekt bietet Zugriff auf verschiedene Informationen über die eingehende Anfrage, einschließlich Header, Abfrageparameter und den Anfragekörper.
Headers
Sie können auf Anfrage-Header mit der Eigenschaft request.headers
zugreifen:
export async function GET(request: Request) {
const userAgent = request.headers.get('user-agent');
console.log('User Agent:', userAgent);
return NextResponse.json({ userAgent });
}
Abfrageparameter
Um auf Abfrageparameter zuzugreifen, können Sie den URL
-Konstruktor verwenden:
export async function GET(request: Request) {
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
const id = searchParams.get('id');
console.log('ID:', id);
return NextResponse.json({ id });
}
Anfragekörper (Request Body)
Bei POST-, PUT- und PATCH-Anfragen können Sie je nach Inhaltstyp mit den Methoden request.json()
oder request.text()
auf den Anfragekörper zugreifen.
export async function POST(request: Request) {
const data = await request.json();
console.log('Data:', data);
return NextResponse.json({ receivedData: data });
}
Antworten zurückgeben
Das NextResponse
-Objekt wird zum Erstellen von API-Antworten verwendet. Es bietet mehrere Methoden zum Festlegen von Headern, Statuscodes und Antwortkörpern.
JSON-Antworten
Verwenden Sie die Methode NextResponse.json()
, um JSON-Antworten zurückzugeben:
return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });
Text-Antworten
Verwenden Sie den Konstruktor new Response()
, um einfache Text-Antworten zurückzugeben:
return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });
Weiterleitungen
Verwenden Sie NextResponse.redirect()
, um Benutzer zu einer anderen URL weiterzuleiten:
import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.redirect(new URL('/new-location', request.url));
}
Header setzen
Sie können benutzerdefinierte Header mit der headers
-Option in NextResponse.json()
oder new Response()
setzen:
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });
Middleware-Integration
Middleware ermöglicht es Ihnen, Code auszuführen, bevor eine Anfrage von Ihrem Route Handler verarbeitet wird. Dies ist nützlich für Authentifizierung, Autorisierung, Protokollierung und andere übergreifende Belange.
Um eine Middleware zu erstellen, erstellen Sie eine Datei namens middleware.ts
(oder middleware.js
) im app
-Verzeichnis oder einem beliebigen Unterverzeichnis. Die Middleware wird auf alle Routen in diesem Verzeichnis und seinen Unterverzeichnissen angewendet.
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/protected/:path*'], // Diese Middleware auf Pfade anwenden, die mit /protected/ beginnen
};
Erklärung:
- Die
middleware
-Funktion prüft auf ein Authentifizierungs-Token in den Anfrage-Cookies. - Wenn das Token fehlt, leitet sie den Benutzer zur Anmeldeseite weiter.
- Andernfalls lässt sie die Anfrage zum Route Handler durch.
- Das
config
-Objekt gibt an, dass diese Middleware nur auf Routen angewendet werden soll, die mit/protected/
beginnen.
Fehlerbehandlung
Eine ordnungsgemäße Fehlerbehandlung ist für die Erstellung robuster APIs von entscheidender Bedeutung. Sie können try...catch
-Blöcke verwenden, um Ausnahmen abzufangen und entsprechende Fehlerantworten zurückzugeben.
export async function GET(request: Request) {
try {
// Einen Fehler simulieren
throw new Error('Something went wrong!');
} catch (error: any) {
console.error('Error:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Erklärung:
- Der
try...catch
-Block fängt alle Ausnahmen ab, die innerhalb des Route Handlers auftreten. - Im
catch
-Block wird der Fehler protokolliert und eine Fehlerantwort mit dem Statuscode 500 Internal Server Error zurückgegeben.
Streaming-Antworten
Route Handlers unterstützen Streaming-Antworten, wodurch Sie Daten schrittweise an den Client senden können. Dies ist besonders nützlich für große Datensätze oder lang andauernde Prozesse.
import { Readable } from 'stream';
import { NextResponse } from 'next/server';
async function* generateData() {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Verzögerung simulieren
yield `Data chunk ${i}\n`;
}
}
export async function GET(request: Request) {
const readableStream = Readable.from(generateData());
return new Response(readableStream, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
Erklärung:
- Die Funktion
generateData
ist ein asynchroner Generator, der Datenblöcke mit einer Verzögerung liefert. - Die Methode
Readable.from()
erstellt einen lesbaren Stream aus dem Generator. - Das
Response
-Objekt wird mit dem lesbaren Stream als Körper erstellt, und derContent-Type
-Header wird auftext/plain
gesetzt.
Authentifizierung und Autorisierung
Die Sicherung Ihrer API-Endpunkte ist von entscheidender Bedeutung. Sie können Authentifizierung und Autorisierung mithilfe von Middleware oder direkt in Ihren Route Handlers implementieren.
Authentifizierung
Authentifizierung überprüft die Identität des Benutzers, der die Anfrage stellt. Gängige Authentifizierungsmethoden sind:
- JWT (JSON Web Tokens): Erzeugen Sie bei erfolgreicher Anmeldung ein Token und überprüfen Sie es bei nachfolgenden Anfragen.
- Sitzungsbasierte Authentifizierung: Verwenden Sie Cookies, um Sitzungs-IDs zu speichern und sie bei jeder Anfrage zu überprüfen.
- OAuth: Delegieren Sie die Authentifizierung an einen Drittanbieter wie Google oder Facebook.
Hier ist ein Beispiel für die JWT-Authentifizierung mit Middleware:
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';
const secret = process.env.JWT_SECRET || 'your-secret-key'; // Ersetzen Sie dies durch ein starkes, zufällig generiertes Geheimnis
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.json({ message: 'Authentication required' }, { status: 401 });
}
try {
jwt.verify(token, secret);
return NextResponse.next();
} catch (error) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
}
}
export const config = {
matcher: ['/api/protected/:path*'],
};
Autorisierung
Autorisierung bestimmt, auf welche Ressourcen ein Benutzer zugreifen darf. Dies basiert typischerweise auf Rollen oder Berechtigungen.
Sie können die Autorisierung in Ihren Route Handlers implementieren, indem Sie die Rollen oder Berechtigungen des Benutzers überprüfen und einen Fehler zurückgeben, wenn er keinen Zugriff hat.
// app/api/admin/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Angenommen, Sie haben eine Funktion, um die Rolle des Benutzers aus dem Token oder der Sitzung zu erhalten
const userRole = await getUserRole(request);
if (userRole !== 'admin') {
return NextResponse.json({ message: 'Unauthorized' }, { status: 403 });
}
// Logik zum Abrufen von Admin-Daten
const adminData = { message: 'Admin data' };
return NextResponse.json(adminData);
}
async function getUserRole(request: Request): Promise {
// Ersetzen Sie dies durch Ihre tatsächliche Logik, um die Rolle des Benutzers aus der Anfrage zu extrahieren
// Dies könnte die Überprüfung eines JWT-Tokens oder einer Sitzung beinhalten
return 'admin'; // Beispiel: fest codierte Rolle zur Demonstration
}
Bereitstellen von Route Handlers
Route Handlers werden als serverlose Funktionen auf Ihrem gewählten Hosting-Anbieter bereitgestellt. Next.js unterstützt verschiedene Bereitstellungsplattformen, darunter Vercel, Netlify, AWS und mehr.
Für Vercel ist die Bereitstellung so einfach wie das Verbinden Ihres Git-Repositorys mit Vercel und das Pushen Ihres Codes. Vercel erkennt Ihr Next.js-Projekt automatisch und stellt Ihre Route Handlers als serverlose Funktionen bereit.
Fortgeschrittene Techniken
Edge Functions
Route Handlers können als Edge Functions bereitgestellt werden, die am Rande eines CDN, näher bei Ihren Benutzern, ausgeführt werden. Dies kann die Latenz erheblich reduzieren und die Leistung verbessern.
Um einen Route Handler als Edge Function bereitzustellen, fügen Sie die edge
-Laufzeit zu Ihrer route.ts
-Datei hinzu:
export const runtime = 'edge';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from the Edge!' });
}
Server Actions
Server Actions ermöglichen es Ihnen, serverseitigen Code direkt aus Ihren React-Komponenten auszuführen. Route Handlers und Server Actions arbeiten nahtlos zusammen, sodass Sie komplexe Anwendungen mit Leichtigkeit erstellen können.
Hier ist ein Beispiel für die Verwendung einer Server Action, um einen Route Handler aufzurufen:
// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
async function handleSubmit(data: FormData) {
'use server';
const name = data.get('name');
const email = data.get('email');
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ name, email }),
});
if (response.ok) {
router.refresh(); // Die Seite aktualisieren, um die Änderungen zu übernehmen
}
}
export default function MyComponent() {
const router = useRouter();
return (
);
}
Caching
Caching kann die Leistung Ihrer API-Endpunkte erheblich verbessern. Sie können den Cache-Control
-Header verwenden, um zu steuern, wie Ihre Antworten von Browsern und CDNs zwischengespeichert werden.
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });
Dieses Beispiel setzt den Cache-Control
-Header auf public, max-age=3600
, was Browsern und CDNs anweist, die Antwort für eine Stunde zwischenzuspeichern.
Best Practices
- Verwenden Sie TypeScript: Nutzen Sie die Typsicherheit von TypeScript, um die Codequalität zu verbessern und Fehler zu vermeiden.
- Validieren Sie Anfragen: Validieren Sie eingehende Anfragen, um die Datenintegrität zu gewährleisten und böswillige Eingaben zu verhindern.
- Behandeln Sie Fehler elegant: Implementieren Sie eine ordnungsgemäße Fehlerbehandlung, um Clients informative Fehlermeldungen bereitzustellen.
- Sichern Sie Ihre Endpunkte: Implementieren Sie Authentifizierung und Autorisierung, um Ihre API-Endpunkte zu schützen.
- Verwenden Sie Middleware: Nutzen Sie Middleware für übergreifende Belange wie Authentifizierung, Protokollierung und Anforderungsvalidierung.
- Zwischenspeichern Sie Antworten: Verwenden Sie Caching, um die Leistung Ihrer API-Endpunkte zu verbessern.
- Überwachen Sie Ihre APIs: Überwachen Sie Ihre APIs, um Probleme schnell zu identifizieren und zu beheben.
- Dokumentieren Sie Ihre APIs: Dokumentieren Sie Ihre APIs, um sie für andere Entwickler einfach nutzbar zu machen. Erwägen Sie die Verwendung von Tools wie Swagger/OpenAPI für die API-Dokumentation.
Praxisbeispiele
Hier sind einige Praxisbeispiele, wie Route Handlers verwendet werden können:
- E-Commerce-API: Erstellen Sie API-Endpunkte zur Verwaltung von Produkten, Bestellungen und Benutzern.
- Social-Media-API: Erstellen Sie API-Endpunkte zum Posten von Tweets, zum Folgen von Benutzern und zum Abrufen von Timelines.
- Content-Management-System (CMS)-API: Erstellen Sie API-Endpunkte zur Verwaltung von Inhalten, Benutzern und Einstellungen.
- Datenanalyse-API: Erstellen Sie API-Endpunkte zum Sammeln und Analysieren von Daten. Zum Beispiel könnte ein Route Handler Daten von Tracking-Pixeln auf verschiedenen Websites empfangen und die Informationen für Berichte aggregieren.
Beispiel für internationalen E-Commerce: Ein Route Handler, der verwendet wird, um Produktpreise basierend auf dem Land des Benutzers abzurufen. Der Endpunkt könnte die Geolokalisierung der Anfrage (abgeleitet von der IP-Adresse) verwenden, um den Standort des Benutzers zu bestimmen und die Preise in der entsprechenden Währung zurückzugeben. Dies trägt zu einem lokalisierten Einkaufserlebnis bei.
Beispiel für globale Authentifizierung: Ein Route Handler, der eine Multi-Faktor-Authentifizierung (MFA) für Benutzer weltweit implementiert. Dies könnte das Senden von SMS-Codes oder die Verwendung von Authenticator-Apps umfassen, wobei die Datenschutzbestimmungen und Telekommunikationsinfrastrukturen der verschiedenen Regionen berücksichtigt werden.
Mehrsprachige Inhaltsauslieferung: Ein Route Handler, der Inhalte in der bevorzugten Sprache des Benutzers liefert. Dies kann aus dem `Accept-Language`-Header in der Anfrage ermittelt werden. Dieses Beispiel unterstreicht die Notwendigkeit einer korrekten UTF-8-Kodierung und gegebenenfalls der Unterstützung von Rechts-nach-Links-Sprachen.
Fazit
Next.js Route Handlers bieten eine leistungsstarke und flexible Möglichkeit, API-Endpunkte direkt in Ihrer Next.js-Anwendung zu erstellen. Durch die Nutzung von Route Handlers können Sie mühelos robuste APIs erstellen, Ihre Backend-Logik zusammen mit Ihren React-Komponenten platzieren und Funktionen wie Middleware, Streaming und Edge Functions nutzen.
Dieser umfassende Leitfaden hat alles von der Grundeinrichtung bis zu fortgeschrittenen Techniken abgedeckt. Indem Sie die in diesem Leitfaden beschriebenen Best Practices befolgen, können Sie qualitativ hochwertige APIs erstellen, die sicher, performant und wartbar sind.