Spec-Zone.ru › Next.js

Перенаправление

Существует несколько способов обработки перенаправлений в Next.js. На этой странице будут рассмотрены все доступные варианты, примеры использования и способы управления большим количеством перенаправлений.

API Цель Место Код состояния
redirect Перенаправление пользователя после мутации или события Компоненты сервера, Действия сервера, Обработчики маршрутов 307 (Временное) или 303 (Действие сервера)
permanentRedirect Перенаправление пользователя после мутации или события Компоненты сервера, Действия сервера, Обработчики маршрутов 308 (Постоянное)
useRouter Выполнение навигации на стороне клиента Обработчики событий в компонентах клиента N/A
redirects в next.config.js Перенаправление входящего запроса на основе пути next.config.js файл 307 (Временное) или 308 (Постоянное)
NextResponse.redirect Перенаправление входящего запроса на основе условия Средства промежуточного слоя Любой

Функция redirect

Функция redirect позволяет перенаправить пользователя на другой URL. Вы можете вызвать redirect в Компонентах сервера, Обработчиках маршрутов и Действиях сервера.

Функция redirect часто используется после мутации или события. Например, при создании поста:

'use server'
 
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'
 
export async function createPost(id: string) {
  try {
    // Call database
  } catch (error) {
    // Handle errors
  }
 
  revalidatePath('/posts') // Update cached posts
  redirect(`/post/${id}`) // Navigate to the new post page
}

Важно знать:

  • redirect по умолчанию возвращает код состояния 307 (Временное перенаправление). При использовании в Действии сервера она возвращает 303 (Перейти к другому ресурсу), что обычно используется для перенаправления на страницу успеха в результате запроса POST.
  • redirect внутренне генерирует ошибку, поэтому её следует вызывать вне блоков try/catch.
  • redirect можно вызывать в Компонентах клиента во время процесса рендеринга, но не в обработчиках событий. Вместо этого используйте useRouter хук.
  • redirect также принимает абсолютные URL и может использоваться для перенаправления на внешние ссылки.
  • Если вы хотите перенаправить до процесса рендеринга, используйте next.config.js или Средства промежуточного слоя.

Дополнительную информацию см. в redirect справочнике API.

Функция permanentRedirect

Функция permanentRedirect позволяет постоянно перенаправить пользователя на другой URL. Вы можете вызвать permanentRedirect в Компонентах сервера, Обработчиках маршрутов и Действиях сервера.

Функция permanentRedirect часто используется после мутации или события, изменяющего канонический URL сущности, например, при обновлении URL профиля пользователя после изменения им своего имени пользователя:

'use server'
 
import { permanentRedirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
 
export async function updateUsername(username: string, formData: FormData) {
  try {
    // Call database
  } catch (error) {
    // Handle errors
  }
 
  revalidateTag('username') // Update all references to the username
  permanentRedirect(`/profile/${username}`) // Navigate to the new user profile
}

Важно знать:

  • permanentRedirect по умолчанию возвращает код состояния 308 (постоянное перенаправление).
  • permanentRedirect также принимает абсолютные URL и может использоваться для перенаправления на внешние ссылки.
  • Если вы хотите перенаправить до процесса рендеринга, используйте next.config.js или Средства промежуточного слоя.

Дополнительную информацию см. в permanentRedirect справочнике API.

Хук useRouter()

Если вам нужно перенаправление внутри обработчика события в Компоненте клиента, вы можете использовать метод push из хука useRouter. Например:

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

Важно знать:

  • Если вам не нужно программно перенаправлять пользователя, используйте компонент <Link>.

Дополнительную информацию см. в useRouter справочнике API.

Перенаправления в next.config.js

Опция redirects в файле next.config.js позволяет перенаправлять входящий запрос по пути на другой путь назначения. Это полезно при изменении структуры URL-адресов страниц или наличии заранее известного списка перенаправлений.

redirects поддерживает сопоставление по пути, сопоставление по заголовкам, cookie и параметрам запроса, что предоставляет гибкость перенаправления пользователей на основе входящего запроса.

Чтобы использовать redirects, добавьте опцию в свой файл next.config.js:

module.exports = {
  async redirects() {
    return [
      // Basic redirect
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
      // Wildcard path matching
      {
        source: '/blog/:slug',
        destination: '/news/:slug',
        permanent: true,
      },
    ]
  },
}

Дополнительную информацию см. в redirects справочнике API.

Важно знать:

  • redirects может возвращать код состояния 307 (временное перенаправление) или 308 (постоянное перенаправление) с помощью опции permanent.
  • redirects может иметь ограничения на платформах. Например, на Vercel существует ограничение в 1024 перенаправления. Для управления большим количеством перенаправлений (более 1000) рассмотрите создание собственного решения с использованием Средств промежуточного слоя. Дополнительные сведения см. в разделе управление перенаправлениями в масштабе.
  • redirects выполняется перед Средствами промежуточного слоя.

NextResponse.redirect в Средствах промежуточного слоя

Средства промежуточного слоя позволяют выполнить код до завершения запроса. Затем, на основе входящего запроса, перенаправьте пользователя на другой URL с помощью NextResponse.redirect. Это полезно, если вы хотите перенаправить пользователей на основе условия (например, аутентификация, управление сессиями и т.д.) или имеете большое количество перенаправлений.

Например, для перенаправления пользователя на страницу /login в случае отсутствия аутентификации:

import { NextResponse, NextRequest } from 'next/server'
import { authenticate } from 'auth-provider'
 
export function middleware(request: NextRequest) {
  const isAuthenticated = authenticate(request)
 
  // If the user is authenticated, continue as normal
  if (isAuthenticated) {
    return NextResponse.next()
  }
 
  // Redirect to login page if not authenticated
  return NextResponse.redirect(new URL('/login', request.url))
}
 
export const config = {
  matcher: '/dashboard/:path*',
}

Важно знать:

  • Средства промежуточного слоя выполняются после redirects в next.config.js и перед рендерингом.

Дополнительную информацию см. в документации по Средствам промежуточного слоя.

Управление перенаправлениями в масштабе (расширенный)

Для управления большим количеством перенаправлений (более 1000) вы можете рассмотреть создание пользовательского решения с использованием Средств промежуточного слоя. Это позволит обрабатывать перенаправления программно без необходимости повторной развертывания приложения.

Для этого необходимо учитывать:

  1. Создание и хранение карты перенаправлений.
  2. Оптимизация производительности поиска данных.

Пример Next.js: Обратитесь к нашему примеру Средств промежуточного слоя с Bloom-фильтром для реализации рекомендаций ниже.

1. Создание и хранение карты перенаправлений

Карта перенаправлений — это список перенаправлений, который можно хранить в базе данных (обычно хранилище ключ-значение) или файле JSON.

Рассмотрите следующую структуру данных:

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

В Средствах промежуточного слоя вы можете читать из базы данных, например, из Конфигурации кэша Vercel или Redis, и перенаправлять пользователя на основе входящего запроса:

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)
  }
 
  // No redirect found, continue without redirecting
  return NextResponse.next()
}

2. Оптимизация производительности поиска данных

Чтение большого набора данных для каждого входящего запроса может быть медленным и дорогостоящим. Существуют два способа оптимизации производительности поиска данных:

  • Используйте базу данных, оптимизированную для быстрых чтений, например, Конфигурацию кэша Vercel или Redis.
  • Используйте стратегию поиска данных, такую как Bloom-фильтр, для эффективной проверки наличия перенаправления перед чтением большего файла перенаправлений или базы данных.

Рассматривая предыдущий пример, вы можете импортировать сгенерированный Bloom-фильтр в Средства промежуточного слоя, а затем проверить, существует ли входящий запрос pathname в Bloom-фильтре.

Если да, перенаправьте запрос в Обработчик маршрутов, который проверит фактический файл и перенаправит пользователя на соответствующий URL. Это позволяет избежать импорта большого файла перенаправлений в Средства промежуточного слоя, что может замедлить каждый входящий запрос.

import { NextResponse, NextRequest } from 'next/server'
import { ScalableBloomFilter } from 'bloom-filters'
import GeneratedBloomFilter from './redirects/bloom-filter.json'
 
type RedirectEntry = {
  destination: string
  permanent: boolean
}
 
// Initialize bloom filter from a generated JSON file
const bloomFilter = ScalableBloomFilter.fromJSON(GeneratedBloomFilter as any)
 
export async function middleware(request: NextRequest) {
  // Get the path for the incoming request
  const pathname = request.nextUrl.pathname
 
  // Check if the path is in the bloom filter
  if (bloomFilter.has(pathname)) {
    // Forward the pathname to the Route Handler
    const api = new URL(
      `/api/redirects?pathname=${encodeURIComponent(request.nextUrl.pathname)}`,
      request.nextUrl.origin
    )
 
    try {
      // Fetch redirect data from the Route Handler
      const redirectData = await fetch(api)
 
      if (redirectData.ok) {
        const redirectEntry: RedirectEntry | undefined =
          await redirectData.json()
 
        if (redirectEntry) {
          // Determine the status code
          const statusCode = redirectEntry.permanent ? 308 : 307
 
          // Redirect to the destination
          return NextResponse.redirect(redirectEntry.destination, statusCode)
        }
      }
    } catch (error) {
      console.error(error)
    }
  }
 
  // No redirect found, continue the request without redirecting
  return NextResponse.next()
}

Затем, в Обработчике маршрутов:

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('Bad Request', { status: 400 })
  }
 
  // Get the redirect entry from the redirects.json file
  const redirect = (redirects as Record<string, RedirectEntry>)[pathname]
 
  // Account for bloom filter false positives
  if (!redirect) {
    return new Response('No redirect', { status: 400 })
  }
 
  // Return the redirect entry
  return NextResponse.json(redirect)
}

Важно знать:

  • Для генерации Bloom-фильтра можно использовать библиотеку, такую как bloom-filters.
  • Вы должны проверять запросы, направляемые в ваш Обработчик маршрутов, чтобы предотвратить вредоносные запросы.

© 2024 Vercel, Inc.
Licensed under the MIT License.
https://nextjs.org/docs/app/building-your-application/routing/redirecting

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API