Umgang mit Weiterleitungen in Next.js

Es gibt mehrere Möglichkeiten, Weiterleitungen in Next.js zu handhaben. Diese Seite stellt jede verfügbare Option vor, zeigt Anwendungsfälle und erklärt den Umgang mit einer großen Anzahl von Weiterleitungen.

APIZweckOrtStatuscode
useRouterClient-seitige Navigation durchführenComponentsN/A
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

useRouter() Hook

Wenn Sie in einer Komponente eine Weiterleitung durchführen müssen, können Sie die push Methode des useRouter Hooks verwenden. Beispiel:

import { useRouter } from 'next/router'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}

Wissenswertes:

  • Wenn Sie keine programmatische Navigation benötigen, sollten Sie eine <Link> Komponente verwenden.

Weitere Informationen finden Sie in der useRouter API-Referenz.

redirects in next.config.js

Die redirects Option in der next.config.js Datei ermöglicht es, eine eingehende Anfrage basierend auf einem Pfad zu einem anderen Zielpfad weiterzuleiten. Dies ist nützlich, wenn Sie die URL-Struktur von Seiten ändern oder eine Liste von Weiterleitungen im Voraus kennen.

redirects unterstützt Pfad, Header-, Cookie- und Query-Matching, was Ihnen die Flexibilität gibt, Benutzer basierend auf einer eingehenden Anfrage weiterzuleiten.

Um redirects zu verwenden, fügen Sie die Option zu Ihrer next.config.js Datei hinzu:

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  async redirects() {
    return [
      // Einfache Weiterleitung
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
      // Wildcard-Pfad-Matching
      {
        source: '/blog/:slug',
        destination: '/news/:slug',
        permanent: true,
      },
    ]
  },
}

export default nextConfig

Weitere Informationen finden Sie in der redirects API-Referenz.

Wissenswertes:

  • redirects kann einen 307 (Temporäre Weiterleitung) oder 308 (Permanente Weiterleitung) Statuscode mit der permanent Option zurückgeben.
  • redirects kann auf Plattformen ein Limit haben. Auf Vercel gibt es beispielsweise ein Limit von 1.024 Weiterleitungen. Um eine große Anzahl von Weiterleitungen (1000+) zu verwalten, sollten Sie eine benutzerdefinierte Lösung mit Middleware erstellen. Siehe Verwaltung von Weiterleitungen im großen Maßstab für mehr Informationen.
  • redirects wird vor Middleware ausgeführt.

NextResponse.redirect in Middleware

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

Um beispielsweise einen Benutzer zur /login Seite weiterzuleiten, wenn er nicht authentifiziert ist:

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, normal fortfahren
  if (isAuthenticated) {
    return NextResponse.next()
  }

  // Zur Login-Seite weiterleiten, wenn nicht authentifiziert
  return NextResponse.redirect(new URL('/login', request.url))
}

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

Wissenswertes:

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

Weitere Informationen finden Sie in der Middleware Dokumentation.

Verwaltung von Weiterleitungen im großen Maßstab (fortgeschritten)

Um eine große Anzahl von Weiterleitungen (1000+) zu verwalten, können Sie eine benutzerdefinierte Lösung mit Middleware erstellen. Dies ermöglicht es Ihnen, Weiterleitungen programmatisch zu handhaben, ohne Ihre Anwendung neu bereitstellen zu müssen.

Dafür müssen Sie folgende Punkte beachten:

  1. Erstellung und Speicherung einer Weiterleitungs-Map.
  2. Optimierung der Datenabfrage-Performance.

Next.js Beispiel: Sehen Sie sich unser Middleware mit Bloom-Filter Beispiel an, das die untenstehenden Empfehlungen umsetzt.

1. Erstellung und Speicherung einer Weiterleitungs-Map

Eine Weiterleitungs-Map ist eine Liste von Weiterleitungen, die Sie in einer Datenbank (normalerweise einem Key-Value-Store) oder einer JSON-Datei speichern können.

Betrachten Sie die folgende Datenstruktur:

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

In Middleware können Sie aus einer Datenbank wie Vercels Edge Config oder Redis lesen und den Benutzer basierend auf der eingehenden Anfrage weiterleiten:

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()
}

2. Optimierung der Datenabfrageleistung

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

  • Verwenden Sie eine Datenbank, die für schnelle Lesezugriffe optimiert ist
  • Verwenden Sie eine Datenabfragestrategie wie einen Bloom-Filter, um effizient zu prüfen, ob eine Weiterleitung existiert, bevor die größere Weiterleitungsdatei oder Datenbank gelesen wird.

Basierend auf dem vorherigen Beispiel können Sie eine generierte Bloom-Filter-Datei in die Middleware importieren und dann prüfen, ob der Pfadname der eingehenden Anfrage im Bloom-Filter vorhanden ist.

Falls ja, leiten Sie die Anfrage an einen API-Route weiter, der die tatsächliche Datei überprüft und den Benutzer zur entsprechenden URL weiterleitet. Dadurch wird vermieden, dass eine große Weiterleitungsdatei in die Middleware importiert wird, was jede eingehende Anfrage verlangsamen könnte.

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) {
  // Pfad für die eingehende Anfrage abrufen
  const pathname = request.nextUrl.pathname

  // Prüfen, ob der Pfad im Bloom-Filter vorhanden ist
  if (bloomFilter.has(pathname)) {
    // 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 abfragen
      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()
}

Dann in der API-Route:

import type { NextApiRequest, NextApiResponse } from 'next'
import redirects from '@/app/redirects/redirects.json'

type RedirectEntry = {
  destination: string
  permanent: boolean
}

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const pathname = req.query.pathname
  if (!pathname) {
    return res.status(400).json({ message: 'Bad Request' })
  }

  // Weiterleitungseintrag aus der redirects.json-Datei abrufen
  const redirect = (redirects as Record<string, RedirectEntry>)[pathname]

  // Falschpositive des Bloom-Filters berücksichtigen
  if (!redirect) {
    return res.status(400).json({ message: 'No redirect' })
  }

  // Weiterleitungseintrag zurückgeben
  return res.json(redirect)
}

Gut zu wissen:

  • 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.

On this page