Deutsch

Entdecken Sie die Next.js-Middleware, eine leistungsstarke Funktion zum Abfangen und Ändern eingehender Anfragen. Lernen Sie mit praktischen Beispielen, wie Sie Authentifizierung, Autorisierung, Weiterleitung und A/B-Tests implementieren.

Next.js Middleware: Meisterung der Request-Interception für dynamische Anwendungen

Next.js-Middleware bietet eine flexible und leistungsstarke Möglichkeit, eingehende Anfragen abzufangen und zu ändern, bevor sie Ihre Routen erreichen. Diese Fähigkeit ermöglicht es Ihnen, eine breite Palette von Funktionen zu implementieren, von Authentifizierung und Autorisierung bis hin zu Weiterleitungen und A/B-Tests, und das alles bei gleichzeitiger Leistungsoptimierung. Dieser umfassende Leitfaden führt Sie durch die Kernkonzepte der Next.js-Middleware und zeigt Ihnen, wie Sie diese effektiv nutzen können.

Was ist Next.js Middleware?

Middleware in Next.js ist eine Funktion, die ausgeführt wird, bevor eine Anfrage abgeschlossen ist. Sie ermöglicht es Ihnen:

Middleware-Funktionen werden in der Datei middleware.ts (oder middleware.js) im Stammverzeichnis Ihres Projekts definiert. Sie werden für jede Route in Ihrer Anwendung ausgeführt oder für bestimmte Routen, basierend auf konfigurierbaren Matchern.

Schlüsselkonzepte und Vorteile

Request-Objekt

Das request-Objekt bietet Zugriff auf Informationen über die eingehende Anfrage, einschließlich:

Response-Objekt

Middleware-Funktionen geben ein Response-Objekt zurück, um das Ergebnis der Anfrage zu steuern. Sie können die folgenden Antworten verwenden:

Matcher

Matcher ermöglichen es Ihnen festzulegen, auf welche Routen Ihre Middleware angewendet werden soll. Sie können Matcher mithilfe von regulären Ausdrücken oder Pfadmustern definieren. Dies stellt sicher, dass Ihre Middleware nur bei Bedarf ausgeführt wird, was die Leistung verbessert und den Overhead reduziert.

Edge Runtime

Next.js-Middleware wird in der Edge Runtime ausgeführt, einer leichtgewichtigen JavaScript-Laufzeitumgebung, die nahe bei Ihren Benutzern bereitgestellt werden kann. Diese Nähe minimiert die Latenz und verbessert die Gesamtleistung Ihrer Anwendung, insbesondere für global verteilte Benutzer. Die Edge Runtime ist im Edge Network von Vercel und auf anderen kompatiblen Plattformen verfügbar. Die Edge Runtime hat einige Einschränkungen, insbesondere bei der Verwendung von Node.js-APIs.

Praktische Beispiele: Implementierung von Middleware-Funktionen

1. Authentifizierung

Authentifizierungs-Middleware kann verwendet werden, um Routen zu schützen, für die Benutzer angemeldet sein müssen. Hier ist ein Beispiel, wie man die Authentifizierung mit Cookies implementiert:


// 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: ['/dashboard/:path*'],
}

Diese Middleware prüft das Vorhandensein eines auth_token-Cookies. Wenn das Cookie nicht gefunden wird, wird der Benutzer zur Seite /login umgeleitet. Der config.matcher legt fest, dass diese Middleware nur für Routen unter /dashboard ausgeführt werden soll.

Globale Perspektive: Passen Sie die Authentifizierungslogik an, um verschiedene Authentifizierungsmethoden (z. B. OAuth, JWT) zu unterstützen und integrieren Sie verschiedene Identitätsanbieter (z. B. Google, Facebook, Azure AD), um Benutzer aus unterschiedlichen Regionen zu bedienen.

2. Autorisierung

Autorisierungs-Middleware kann verwendet werden, um den Zugriff auf Ressourcen basierend auf Benutzerrollen oder Berechtigungen zu steuern. Beispielsweise könnten Sie ein Admin-Dashboard haben, auf das nur bestimmte Benutzer zugreifen können.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Beispiel: Benutzerrollen von einer API abrufen (durch Ihre tatsächliche Logik ersetzen)
 const userResponse = await fetch('https://api.example.com/userinfo', {
 headers: {
 Authorization: `Bearer ${token}`,
 },
 });
 const userData = await userResponse.json();

 if (userData.role !== 'admin') {
 return NextResponse.redirect(new URL('/unauthorized', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/admin/:path*'],
}

Diese Middleware ruft die Rolle des Benutzers ab und prüft, ob er die Rolle admin hat. Wenn nicht, wird er zu einer /unauthorized-Seite umgeleitet. Dieses Beispiel verwendet einen Platzhalter-API-Endpunkt. Ersetzen Sie `https://api.example.com/userinfo` durch Ihren tatsächlichen Authentifizierungsserver-Endpunkt.

Globale Perspektive: Achten Sie beim Umgang mit Benutzerdaten auf Datenschutzbestimmungen (z. B. DSGVO, CCPA). Implementieren Sie angemessene Sicherheitsmaßnahmen, um sensible Informationen zu schützen und die Einhaltung lokaler Gesetze zu gewährleisten.

3. Weiterleitung

Weiterleitungs-Middleware kann verwendet werden, um Benutzer basierend auf ihrem Standort, ihrer Sprache oder anderen Kriterien umzuleiten. Sie könnten beispielsweise Benutzer basierend auf ihrer IP-Adresse zu einer lokalisierten Version Ihrer Website weiterleiten.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const country = request.geo?.country || 'US'; // Standardmäßig US, wenn Geolokalisierung fehlschlägt

 if (country === 'DE') {
 return NextResponse.redirect(new URL('/de', request.url))
 }

 if (country === 'FR') {
 return NextResponse.redirect(new URL('/fr', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/'],
}

Diese Middleware überprüft das Land des Benutzers anhand seiner IP-Adresse und leitet ihn zur entsprechenden lokalisierten Version der Website weiter (/de für Deutschland, /fr für Frankreich). Wenn die Geolokalisierung fehlschlägt, wird standardmäßig die US-Version verwendet. Beachten Sie, dass dies davon abhängt, ob die geo-Eigenschaft verfügbar ist (z. B. bei einer Bereitstellung auf Vercel).

Globale Perspektive: Stellen Sie sicher, dass Ihre Website mehrere Sprachen und Währungen unterstützt. Geben Sie den Benutzern die Möglichkeit, ihre bevorzugte Sprache oder Region manuell auszuwählen. Verwenden Sie für jede Locale die passenden Datums- und Zeitformate.

4. A/B-Testing

Middleware kann verwendet werden, um A/B-Tests zu implementieren, indem Benutzer zufällig verschiedenen Varianten einer Seite zugewiesen und ihr Verhalten verfolgt wird. Hier ist ein vereinfachtes Beispiel:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

function getRandomVariant() {
 return Math.random() < 0.5 ? 'A' : 'B';
}

export function middleware(request: NextRequest) {
 let variant = request.cookies.get('variant')?.value;

 if (!variant) {
 variant = getRandomVariant();
 const response = NextResponse.next();
 response.cookies.set('variant', variant);
 return response;
 }

 if (variant === 'B') {
 return NextResponse.rewrite(new URL('/variant-b', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/'],
}

Diese Middleware weist Benutzer entweder der Variante 'A' oder 'B' zu. Wenn ein Benutzer noch kein variant-Cookie hat, wird eines zufällig zugewiesen und gesetzt. Benutzer, die der Variante 'B' zugewiesen sind, werden zur Seite /variant-b umgeschrieben. Sie würden dann die Leistung jeder Variante verfolgen, um festzustellen, welche effektiver ist.

Globale Perspektive: Berücksichtigen Sie kulturelle Unterschiede bei der Gestaltung von A/B-Tests. Was in einer Region gut funktioniert, findet bei Benutzern in einer anderen möglicherweise keinen Anklang. Stellen Sie sicher, dass Ihre A/B-Testing-Plattform den Datenschutzbestimmungen in verschiedenen Regionen entspricht.

5. Feature Flags

Feature Flags ermöglichen es Ihnen, Funktionen in Ihrer Anwendung zu aktivieren oder zu deaktivieren, ohne neuen Code bereitzustellen. Middleware kann verwendet werden, um festzustellen, ob ein Benutzer basierend auf seiner Benutzer-ID, seinem Standort oder anderen Kriterien Zugriff auf eine bestimmte Funktion haben sollte.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 // Beispiel: Feature Flags von einer API abrufen
 const featureFlagsResponse = await fetch('https://api.example.com/featureflags', {
 headers: {
 'X-User-Id': 'user123',
 },
 });
 const featureFlags = await featureFlagsResponse.json();

 if (featureFlags.new_feature_enabled) {
 // Das neue Feature aktivieren
 return NextResponse.next();
 } else {
 // Das neue Feature deaktivieren (z. B. auf eine alternative Seite umleiten)
 return NextResponse.redirect(new URL('/alternative-page', request.url));
 }
}

export const config = {
 matcher: ['/new-feature'],
}

Diese Middleware ruft Feature Flags von einer API ab und prüft, ob das Flag new_feature_enabled gesetzt ist. Wenn ja, kann der Benutzer auf die Seite /new-feature zugreifen. Andernfalls wird er zu einer /alternative-page umgeleitet.

Globale Perspektive: Verwenden Sie Feature Flags, um neue Funktionen schrittweise für Benutzer in verschiedenen Regionen einzuführen. Dies ermöglicht es Ihnen, die Leistung zu überwachen und Probleme zu beheben, bevor Sie die Funktion einem breiteren Publikum zur Verfügung stellen. Stellen Sie außerdem sicher, dass Ihr Feature-Flagging-System global skaliert und konsistente Ergebnisse unabhängig vom Standort des Benutzers liefert. Berücksichtigen Sie regionale regulatorische Beschränkungen für die Einführung von Funktionen.

Fortgeschrittene Techniken

Verketten von Middleware

Sie können mehrere Middleware-Funktionen miteinander verketten, um eine Reihe von Operationen bei einer Anfrage durchzuführen. Dies kann nützlich sein, um komplexe Logik in kleinere, besser verwaltbare Module zu unterteilen.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const response = NextResponse.next();

 // Erste Middleware-Funktion
 const token = request.cookies.get('auth_token');
 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Zweite Middleware-Funktion
 response.headers.set('x-middleware-custom', 'value');

 return response;
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

Dieses Beispiel zeigt zwei Middlewares in einer. Die erste führt die Authentifizierung durch und die zweite setzt einen benutzerdefinierten Header.

Verwendung von Umgebungsvariablen

Speichern Sie sensible Informationen wie API-Schlüssel und Datenbank-Anmeldeinformationen in Umgebungsvariablen, anstatt sie fest in Ihren Middleware-Funktionen zu codieren. Dies verbessert die Sicherheit und erleichtert die Verwaltung der Konfiguration Ihrer Anwendung.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const API_KEY = process.env.API_KEY;

export async function middleware(request: NextRequest) {
 const response = await fetch('https://api.example.com/data', {
 headers: {
 'X-API-Key': API_KEY,
 },
 });

 // ...
}

export const config = {
 matcher: ['/data'],
}

In diesem Beispiel wird der API_KEY aus einer Umgebungsvariable abgerufen.

Fehlerbehandlung

Implementieren Sie eine robuste Fehlerbehandlung in Ihren Middleware-Funktionen, um zu verhindern, dass unerwartete Fehler Ihre Anwendung zum Absturz bringen. Verwenden Sie try...catch-Blöcke, um Ausnahmen abzufangen und Fehler entsprechend zu protokollieren.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 try {
 const response = await fetch('https://api.example.com/data');
 // ...
 } catch (error) {
 console.error('Error fetching data:', error);
 return NextResponse.error(); // Oder auf eine Fehlerseite umleiten
 }
}

export const config = {
 matcher: ['/data'],
}

Bewährte Methoden

Fehlerbehebung bei häufigen Problemen

Fazit

Next.js-Middleware ist ein leistungsstarkes Werkzeug zur Erstellung dynamischer und personalisierter Webanwendungen. Durch die Meisterung der Request-Interception können Sie eine breite Palette von Funktionen implementieren, von Authentifizierung und Autorisierung bis hin zu Weiterleitungen und A/B-Tests. Indem Sie die in diesem Leitfaden beschriebenen bewährten Methoden befolgen, können Sie die Next.js-Middleware nutzen, um hochleistungsfähige, sichere und skalierbare Anwendungen zu erstellen, die den Anforderungen Ihrer globalen Benutzerbasis gerecht werden. Nutzen Sie die Macht der Middleware, um neue Möglichkeiten in Ihren Next.js-Projekten zu erschließen und außergewöhnliche Benutzererlebnisse zu liefern.