Menu

Weiterleitung

Es gibt mehrere Möglichkeiten, Weiterleitungen in Next.js zu handhaben. Diese Seite geht auf jede verfügbare Option, Anwendungsfälle und die Verwaltung einer großen Anzahl von Weiterleitungen ein.

APIZweckWoStatuscode
redirectBenutzer nach einer Mutation oder einem Ereignis weiterleitenServer-Komponenten, Server-Actions, Route-Handler307 (Temporär) oder 303 (Server-Action)
permanentRedirectBenutzer nach einer Mutation oder einem Ereignis weiterleitenServer-Komponenten, Server-Actions, Route-Handler308 (Permanent)
useRouterClient-seitige Navigation durchführenEreignis-Handler in Client-KomponentenNicht zutreffend
redirects in next.config.jsEingehende Anfrage basierend auf einem Pfad weiterleitennext.config.js-Datei307 (Temporär) oder 308 (Permanent)
NextResponse.redirectEingehende Anfrage basierend auf einer Bedingung weiterleitenMiddlewareBeliebig

redirect-Funktion

Die redirect-Funktion ermöglicht es, Benutzer zu einer anderen URL weiterzuleiten. Sie können redirect in Server-Komponenten, Route-Handlern und Server-Actions aufrufen.

redirect wird häufig nach einer Mutation oder einem Ereignis verwendet. Zum Beispiel beim Erstellen eines Beitrags:

app/actions.tsx
TypeScript
'use server'
 
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
 
export async function createPost(id: string) {
  try {
    // Datenbank aufrufen
  } catch (error) {
    // Fehler behandeln
  }
 
  revalidatePath('/posts') // Zwischengespeicherte Beiträge aktualisieren
  redirect(`/post/${id}`) // Zur neuen Beitragsseite navigieren
}

Hinweis:

  • redirect gibt standardmäßig einen 307-Statuscode (Temporäre Weiterleitung) zurück. Bei Verwendung in einer Server-Action wird ein 303-Statuscode (Andere) zurückgegeben, der häufig zur Weiterleitung zu einer Erfolgsseite nach einer POST-Anfrage verwendet wird.
  • redirect wirft intern einen Fehler, daher sollte es außerhalb von try/catch-Blöcken aufgerufen werden.
  • redirect kann in Client-Komponenten während des Rendering-Prozesses aufgerufen werden, jedoch nicht in Ereignis-Handlern. Verwenden Sie stattdessen den useRouter-Hook.
  • redirect akzeptiert auch absolute URLs und kann zur Weiterleitung zu externen Links verwendet werden.
  • Wenn Sie vor dem Rendering weiterleiten möchten, verwenden Sie next.config.js oder Middleware.

Weitere Informationen finden Sie in der redirect-API-Referenz.

permanentRedirect-Funktion

Die permanentRedirect-Funktion ermöglicht es Ihnen, Benutzer zu einer anderen URL dauerhaft weiterzuleiten. Sie können permanentRedirect in Server-Komponenten, Route-Handlern und Server-Actions aufrufen.

permanentRedirect wird häufig nach einer Mutation oder einem Ereignis verwendet, das die kanonische URL einer Entität ändert, z.B. beim Aktualisieren der Profil-URL eines Benutzers nach einer Änderung des Benutzernamens:

app/actions.ts
TypeScript
'use server'
 
import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
 
export async function updateUsername(username: string, formData: FormData) {
  try {
    // Datenbank aufrufen
  } catch (error) {
    // Fehler behandeln
  }
 
  revalidateTag('username') // Alle Referenzen zum Benutzernamen aktualisieren
  permanentRedirect(`/profile/${username}`) // Zum neuen Benutzerprofil navigieren
}

Hinweis:

  • permanentRedirect gibt standardmäßig einen 308-Statuscode (permanente Weiterleitung) zurück.
  • permanentRedirect akzeptiert auch absolute URLs und kann zur Weiterleitung zu externen Links verwendet werden.
  • Wenn Sie vor dem Rendering weiterleiten möchten, verwenden Sie next.config.js oder Middleware.

Weitere Informationen finden Sie in der permanentRedirect-API-Referenz.

useRouter()-Hook

Wenn Sie in einer Client-Komponente in einem Ereignis-Handler eine Weiterleitung benötigen, können Sie die push-Methode des useRouter-Hooks verwenden. Beispiel:

app/page.tsx
TypeScript
'use client'
 
import { useRouter } from 'next/navigation'
 
export default function Page() {
  const router = useRouter()
 
  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}

Hinweis:

  • Wenn du Benutzer nicht programmgesteuert navigieren musst, solltest du die <Link>-Komponente verwenden.

Weitere Informationen findest du in der useRouter API-Referenz.

redirects in next.config.js

Die Option redirects in der Datei next.config.js erlaubt es, eine eingehende Anfragepfad zu einem anderen Ziel-Pfad umzuleiten. Dies ist nützlich, wenn du die URL-Struktur von Seiten änderst oder eine Liste von Weiterleitungen hast, die im Voraus bekannt sind.

redirects unterstützt Pfad, Header-, Cookie- und Abfrage-Matching und bietet dir die Flexibilität, Benutzer basierend auf einer eingehenden Anfrage weiterzuleiten.

Um redirects zu verwenden, füge die Option zu deiner next.config.js-Datei hinzu:

next.config.js
module.exports = {
  async redirects() {
    return [
      // Einfache Weiterleitung
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
      // Platzhalter-Pfad-Matching
      {
        source: '/blog/:slug',
        destination: '/news/:slug',
        permanent: true,
      },
    ]
  },
}

Weitere Informationen findest du in der redirects API-Referenz.

Hinweis:

  • redirects kann einen 307 (Temporäre Weiterleitung) oder 308 (Permanente Weiterleitung) Statuscode mit der Option permanent zurückgeben.
  • redirects kann auf Plattformen ein Limit haben. Zum Beispiel gibt es bei Vercel ein Limit von 1.024 Weiterleitungen. Um eine große Anzahl von Weiterleitungen (1000+) zu verwalten, solltest du eine benutzerdefinierte Lösung mit Middleware in Betracht ziehen. Weitere Informationen findest du unter Weiterleitungen im großen Maßstab verwalten.
  • redirects wird vor Middleware ausgeführt.

NextResponse.redirect in Middleware

Middleware ermöglicht es, Code auszuführen, bevor eine Anfrage abgeschlossen wird. Dann können Sie basierend auf der eingehenden Anfrage mit NextResponse.redirect zu einer anderen URL weiterleiten. Dies ist nützlich, wenn Sie Benutzer basierend auf einer Bedingung (z.B. Authentifizierung, Sitzungsverwaltung usw.) weiterleiten möchten oder eine große Anzahl von Weiterleitungen haben.

Ein Beispiel, um den Benutzer auf eine /login-Seite weiterzuleiten, wenn er nicht authentifiziert ist:

middleware.ts
TypeScript
import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'
 
export function middleware(request: NextRequest) {
  const isAuthenticated = authenticate(request)
 
  // Wenn der Benutzer authentifiziert ist, fahre normal fort
  if (isAuthenticated) {
    return NextResponse.next()
  }
 
  // Weiterleitung zur Anmeldeseite, wenn nicht authentifiziert
  return NextResponse.redirect(new URL('/login', request.url))
}
 
export const config = {
  matcher: '/dashboard/:path*',
}
middleware.js
import { NextResponse } from 'next/server'
import { authenticate } from 'auth-provider'
 
export function middleware(request) {
  const isAuthenticated = authenticate(request)
 
  // Wenn der Benutzer authentifiziert ist, fahre normal fort
  if (isAuthenticated) {
    return NextResponse.next()
  }
 
  // Weiterleitung zur Anmeldeseite, wenn nicht authentifiziert
  return NextResponse.redirect(new URL('/login', request.url))
}
 
export const config = {
  matcher: '/dashboard/:path*',
}

Hinweis:

  • Middleware wird nach redirects in next.config.js und vor dem Rendering ausgeführt.

Weitere Informationen findest du in der Middleware-Dokumentation.

Weiterleitungen im großen Maßstab verwalten (fortgeschritten)

Um eine große Anzahl von Weiterleitungen (1000+) zu verwalten, solltest du eine benutzerdefinierte Lösung mit Middleware in Betracht ziehen. Dies ermöglicht es dir, Weiterleitungen programmgesteuert zu verarbeiten, ohne die Anwendung neu bereitstellen zu müssen.

Dabei musst du Folgendes berücksichtigen:

  1. Erstellen und Speichern einer Weiterleitungskarte.
  2. Optimieren der Datenlookup-Leistung.

Next.js-Beispiel: Ein Beispiel für die Implementierung der nachfolgenden Empfehlungen findest du in unserem Middleware mit Bloom-Filter-Beispiel.

1. Erstellen und Speichern einer Weiterleitungskarte

Eine Weiterleitungskarte ist eine Liste von Weiterleitungen, die du in einer Datenbank (normalerweise ein Schlüssel-Wert-Speicher) oder einer JSON-Datei speichern kannst.

Betrachte die folgende Datenstruktur:

{
  "/old": {
    "destination": "/new",
    "permanent": true
  },
  "/blog/post-old": {
    "destination": "/blog/post-new",
    "permanent": true
  }
}

In Middleware kannst du aus einer Datenbank wie Vercels Edge Config oder Redis lesen und den Benutzer basierend auf der eingehenden Anfrage weiterleiten:

middleware.ts
TypeScript
import { NextResponse, NextRequest } from 'next/server'
import { get } from '@vercel/edge-config'
 
type RedirectEntry = {
  destination: string
  permanent: boolean
}
 
export async function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname
  const redirectData = await get(pathname)
 
  if (redirectData && typeof redirectData === 'string') {
    const redirectEntry: RedirectEntry = JSON.parse(redirectData)
    const statusCode = redirectEntry.permanent ? 308 : 307
    return NextResponse.redirect(redirectEntry.destination, statusCode)
  }
 
  // Keine Weiterleitung gefunden, ohne Weiterleitung fortfahren
  return NextResponse.next()
}
middleware.js
import { NextResponse } from 'next/server'
import { get } from '@vercel/edge-config'
 
export async function middleware(request) {
  const pathname = request.nextUrl.pathname
  const redirectData = await get(pathname)
 
  if (redirectData) {
    const redirectEntry = JSON.parse(redirectData)
    const statusCode = redirectEntry.permanent ? 308 : 307
    return NextResponse.redirect(redirectEntry.destination, statusCode)
  }
 
  // Keine Weiterleitung gefunden, ohne Weiterleitung fortfahren
  return NextResponse.next()
}

2. Optimieren der Datenlookup-Leistung

Das Lesen eines großen Datensatzes für jede eingehende Anfrage kann langsam und teuer sein. Es gibt zwei Möglichkeiten, die Datenlookup-Leistung zu optimieren:

  • Verwenden Sie eine Datenbank, die für schnelle Lesevorgänge optimiert ist, wie Vercel Edge Config oder Redis.
  • Verwenden Sie eine Datenlookup-Strategie wie einen Bloom-Filter, um effizient zu überprüfen, ob eine Weiterleitung existiert, bevor die größere Weiterleitungsdatei oder -datenbank gelesen wird.

Ausgehend vom vorherigen Beispiel können Sie eine generierte Bloom-Filter-Datei in Middleware importieren und dann überprüfen, ob der eingehende Anfragepfad im Bloom-Filter existiert.

Wenn ja, leiten Sie die Anfrage an einen Route Handler weiter, der die tatsächliche Datei überprüft und den Benutzer zur entsprechenden URL weiterleitet. Dies vermeidet das Importieren einer großen Weiterleitungsdatei in Middleware, was jede eingehende Anfrage verlangsamen kann.

middleware.ts
TypeScript
import { NextResponse, NextRequest } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'
 
type RedirectEntry = {
  destination: string
  permanent: boolean
}
 
// Bloom-Filter aus einer generierten JSON-Datei initialisieren
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter as any)
 
export async function middleware(request: NextRequest) {
  // Den Pfad für die eingehende Anfrage abrufen
  const pathname = request.nextUrl.pathname
 
  // Überprüfen, ob der Pfad im Bloom-Filter enthalten ist
  if (bloomFilter.has(pathname)) {
    // Den Pfadnamen an den Route Handler weiterleiten
    const api = new URL(
      `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
      request.nextUrl.origin
    )
 
    try {
      // Weiterleitungsdaten vom Route Handler abrufen
      const redirectData = await fetch(api)
 
      if (redirectData.ok) {
        const redirectEntry: RedirectEntry | undefined =
          await redirectData.json()
 
        if (redirectEntry) {
          // Statuscode bestimmen
          const statusCode = redirectEntry.permanent ? 308 : 307
 
          // Zur Ziel-URL weiterleiten
          return NextResponse.redirect(redirectEntry.destination, statusCode)
        }
      }
    } catch (error) {
      console.error(error)
    }
  }
 
  // Keine Weiterleitung gefunden, Anfrage ohne Weiterleitung fortsetzen
  return NextResponse.next()
}
middleware.js
import { NextResponse } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'
 
// Bloom-Filter aus einer generierten JSON-Datei initialisieren
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter)
 
export async function middleware(request) {
  // Den Pfad für die eingehende Anfrage abrufen
  const pathname = request.nextUrl.pathname
 
  // Überprüfen, ob der Pfad im Bloom-Filter enthalten ist
  if (bloomFilter.has(pathname)) {
    // Den Pfadnamen an den Route Handler weiterleiten
    const api = new URL(
      `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
      request.nextUrl.origin
    )
 
    try {
      // Weiterleitungsdaten vom Route Handler abrufen
      const redirectData = await fetch(api)
 
      if (redirectData.ok) {
        const redirectEntry = await redirectData.json()
 
        if (redirectEntry) {
          // Statuscode bestimmen
          const statusCode = redirectEntry.permanent ? 308 : 307
 
          // Zur Ziel-URL weiterleiten
          return NextResponse.redirect(redirectEntry.destination, statusCode)
        }
      }
    } catch (error) {
      console.error(error)
    }
  }
 
  // Keine Weiterleitung gefunden, Anfrage ohne Weiterleitung fortsetzen
  return NextResponse.next()
}

Dann, im Route Handler:

app/redirects/route.ts
TypeScript
import { NextRequest, NextResponse } from 'next/server'
import redirects from '@/app/redirects/redirects.json'
 
type RedirectEntry = {
  destination: string
  permanent: boolean
}
 
export function GET(request: NextRequest) {
  const pathname = request.nextUrl.searchParams.get('pathname')
  if (!pathname) {
    return new Response('Ungültige Anfrage', { status: 400 })
  }
 
  // Die Weiterleitungs-Eintragung aus der redirects.json-Datei abrufen
  const redirect = (redirects as Record<string, RedirectEntry>)[pathname]
 
  // Falsch-Positive des Bloom-Filters berücksichtigen
  if (!redirect) {
    return new Response('Keine Weiterleitung', { status: 400 })
  }
 
  // Die Weiterleitungs-Eintragung zurückgeben
  return NextResponse.json(redirect)
}
app/redirects/route.js
import { NextResponse } from 'next/server'
import redirects from '@/app/redirects/redirects.json'
 
export function GET(request) {
  const pathname = request.nextUrl.searchParams.get('pathname')
  if (!pathname) {
    return new Response('Ungültige Anfrage', { status: 400 })
  }
 
  // Die Weiterleitungs-Eintragung aus der redirects.json-Datei abrufen
  const redirect = redirects[pathname]
 
  // Falsch-Positive des Bloom-Filters berücksichtigen
  if (!redirect) {
    return new Response('Keine Weiterleitung', { status: 400 })
  }
 
  // Die Weiterleitungs-Eintragung zurückgeben
  return NextResponse.json(redirect)
}

Hinweis:

  • Um einen Bloom-Filter zu generieren, können Sie eine Bibliothek wie bloom-filters verwenden.
  • Sie sollten Anfragen an Ihren Route Handler validieren, um böswillige Anfragen zu verhindern.