Weiterleitungen
Es gibt mehrere Möglichkeiten, Weiterleitungen in Next.js zu handhaben. Diese Seite stellt jede verfügbare Option vor, erläutert Anwendungsfälle und zeigt, wie Sie eine große Anzahl von Weiterleitungen verwalten können.
API | Zweck | Verwendungsort | Statuscode |
---|---|---|---|
useRouter | Client-seitige Navigation durchführen | Components | N/A |
redirects in next.config.js | Anfrage basierend auf Pfad umleiten | next.config.js Datei | 307 (Temporär) oder 308 (Permanent) |
NextResponse.redirect | Anfrage basierend auf Bedingung umleiten | Middleware | Beliebig |
useRouter()
-Hook
Für Weiterleitungen in Components 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>
)
}
import { useRouter } from 'next/router'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
Gut zu wissen:
- Für nicht-programmatische Navigation 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, eingehende Anfragen basierend auf dem Pfad umzuleiten. Dies ist nützlich bei Änderungen der URL-Struktur oder bei bekannten Weiterleitungen.
redirects
unterstützt Pfad, Header-, Cookie- und Query-Matching für flexible Weiterleitungsregeln.
So verwenden Sie redirects
:
module.exports = {
async redirects() {
return [
// Einfache Weiterleitung
{
source: '/about',
destination: '/',
permanent: true,
},
// Wildcard-Pfad-Matching
{
source: '/blog/:slug',
destination: '/news/:slug',
permanent: true,
},
]
},
}
Weitere Informationen finden Sie in der redirects
-API-Referenz.
Gut zu wissen:
redirects
kann 307 (Temporary Redirect) oder 308 (Permanent Redirect) Statuscodes zurückgeben.- Auf einigen Plattformen gibt es Limits (z.B. 1.024 Weiterleitungen auf Vercel). Für große Mengen (1000+) sollten Sie Middleware verwenden. Siehe Weiterleitungen im großen Stil.
redirects
wird vor Middleware ausgeführt.
NextResponse.redirect
in Middleware
Middleware ermöglicht Code-Ausführung vor Abschluss einer Anfrage. Mit NextResponse.redirect
können Sie basierend auf der Anfrage umleiten, z.B. für Authentifizierung oder Session-Management.
Beispiel für Authentifizierungs-Weiterleitung:
import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'
export function middleware(request: NextRequest) {
const isAuthenticated = authenticate(request)
if (isAuthenticated) {
return NextResponse.next()
}
return NextResponse.redirect(new URL('/login', request.url))
}
export const config = {
matcher: '/dashboard/:path*',
}
import { NextResponse } from 'next/server'
import { authenticate } from 'auth-provider'
export function middleware(request) {
const isAuthenticated = authenticate(request)
if (isAuthenticated) {
return NextResponse.next()
}
return NextResponse.redirect(new URL('/login', request.url))
}
export const config = {
matcher: '/dashboard/:path*',
}
Gut zu wissen:
- Middleware wird nach
redirects
innext.config.js
und vor dem Rendering ausgeführt.
Weitere Informationen finden Sie in der Middleware-Dokumentation.
Weiterleitungen im großen Stil (Fortgeschritten)
Für große Mengen an Weiterleitungen (1000+) können Sie eine benutzerdefinierte Middleware-Lösung erstellen, ohne die Anwendung neu zu deployen.
Dafür benötigen Sie:
- Eine Weiterleitungs-Map
- Optimierte Datenabfrage
Next.js-Beispiel: Siehe unser Middleware mit Bloom-Filter-Beispiel für eine Implementierung.
1. Erstellen und Speichern einer Weiterleitungs-Map
Eine Weiterleitungs-Map ist eine Liste von Weiterleitungen, die in einer Datenbank oder JSON-Datei gespeichert werden kann.
Beispiel-Datenstruktur:
{
"/old": {
"destination": "/new",
"permanent": true
},
"/blog/post-old": {
"destination": "/blog/post-new",
"permanent": true
}
}
In Middleware können Sie aus Datenbanken wie Vercels Edge Config oder Redis lesen:
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)
}
return NextResponse.next()
}
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)
}
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 Lesevorgänge optimiert ist, wie z.B. Vercel Edge Config oder Redis.
- 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.
Bezogen auf das vorherige Beispiel können Sie eine generierte Bloom-Filter-Datei in die Middleware importieren und dann prüfen, ob der Pfad der eingehenden Anfrage im Bloom-Filter enthalten ist.
Falls ja, leiten Sie die Anfrage an einen API-Route weiter, der die eigentliche Datei überprüft und den Benutzer zur entsprechenden URL weiterleitet. Dadurch wird vermieden, eine große Weiterleitungsdatei in die Middleware zu importieren, 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
}
// Initialisiere Bloom-Filter aus einer generierten JSON-Datei
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter as any)
export async function middleware(request: NextRequest) {
// Hole den Pfad der eingehenden Anfrage
const pathname = request.nextUrl.pathname
// Prüfe, ob der Pfad im Bloom-Filter enthalten ist
if (bloomFilter.has(pathname)) {
// Leite den Pfad an den Route Handler weiter
const api = new URL(
`/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
request.nextUrl.origin
)
try {
// Hole Weiterleitungsdaten vom Route Handler
const redirectData = await fetch(api)
if (redirectData.ok) {
const redirectEntry: RedirectEntry | undefined =
await redirectData.json()
if (redirectEntry) {
// Bestimme den Statuscode
const statusCode = redirectEntry.permanent ? 308 : 307
// Leite zur Ziel-URL weiter
return NextResponse.redirect(redirectEntry.destination, statusCode)
}
}
} catch (error) {
console.error(error)
}
}
// Keine Weiterleitung gefunden, Anfrage ohne Weiterleitung fortsetzen
return NextResponse.next()
}
import { NextResponse } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'
// Initialisiere Bloom-Filter aus einer generierten JSON-Datei
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter)
export async function middleware(request) {
// Hole den Pfad der eingehenden Anfrage
const pathname = request.nextUrl.pathname
// Prüfe, ob der Pfad im Bloom-Filter enthalten ist
if (bloomFilter.has(pathname)) {
// Leite den Pfad an den Route Handler weiter
const api = new URL(
`/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
request.nextUrl.origin
)
try {
// Hole Weiterleitungsdaten vom Route Handler
const redirectData = await fetch(api)
if (redirectData.ok) {
const redirectEntry = await redirectData.json()
if (redirectEntry) {
// Bestimme den Statuscode
const statusCode = redirectEntry.permanent ? 308 : 307
// Leite zur Ziel-URL weiter
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 { 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' })
}
// Hole den Weiterleitungseintrag aus der redirects.json-Datei
const redirect = (redirects as Record<string, RedirectEntry>)[pathname]
// Berücksichtige falsch positive Ergebnisse des Bloom-Filters
if (!redirect) {
return res.status(400).json({ message: 'No redirect' })
}
// Gib den Weiterleitungseintrag zurück
return res.json(redirect)
}
import redirects from '@/app/redirects/redirects.json'
export default function handler(req, res) {
const pathname = req.query.pathname
if (!pathname) {
return res.status(400).json({ message: 'Bad Request' })
}
// Hole den Weiterleitungseintrag aus der redirects.json-Datei
const redirect = redirects[pathname]
// Berücksichtige falsch positive Ergebnisse des Bloom-Filters
if (!redirect) {
return res.status(400).json({ message: 'No redirect' })
}
// Gib den Weiterleitungseintrag zurück
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ösartige Anfragen zu verhindern.
Linking und Navigation
Erfahren Sie, wie Navigation in Next.js funktioniert und wie Sie die Link-Komponente sowie den `useRouter`-Hook verwenden.
Benutzerdefinierte App
Steuern der Seiteninitialisierung und Hinzufügen eines Layouts, das für alle Seiten erhalten bleibt, durch Überschreiben der standardmäßigen App-Komponente von Next.js.