Переадресация (rewrites)
Переадресации (rewrites) позволяют сопоставить входящий путь запроса с другим целевым путём.
Переадресации действуют как URL-прокси и маскируют целевой путь, создавая впечатление, что пользователь не изменил своё местоположение на сайте. В отличие от этого, редиректы (redirects) перенаправляют на новую страницу и показывают изменения URL.
Для использования переадресаций вы можете использовать ключ rewrites
в next.config.js
:
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
]
},
}
Переадресации применяются к клиентской маршрутизации, <Link href="/about">
будет иметь применённую переадресацию в приведённом выше примере.
rewrites
— это асинхронная функция, которая должна возвращать либо массив, либо объект массивов (см. ниже), содержащий объекты со свойствами source
и destination
:
source
:String
— шаблон пути входящего запроса.destination
:String
— путь, на который нужно перенаправить.basePath
:false
илиundefined
— если false, basePath не будет учитываться при сопоставлении, может использоваться только для внешних переадресаций.locale
:false
илиundefined
— указывает, следует ли исключать локаль при сопоставлении.has
— массив объектов has со свойствамиtype
,key
иvalue
.missing
— массив объектов missing со свойствамиtype
,key
иvalue
.
Когда функция rewrites
возвращает массив, переадресации применяются после проверки файловой системы (страницы и файлы /public
) и перед динамическими маршрутами. Когда функция rewrites
возвращает объект массивов определённой структуры, это поведение можно изменить и более тонко контролировать, начиная с версии Next.js v10.1
:
module.exports = {
async rewrites() {
return {
beforeFiles: [
// Эти переадресации проверяются после headers/redirects
// и перед всеми файлами, включая _next/public, что
// позволяет переопределять файлы страниц
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// Эти переадресации проверяются после проверки страниц/public файлов,
// но перед динамическими маршрутами
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// Эти переадресации проверяются после проверки как страниц/public файлов,
// так и динамических маршрутов
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
}
},
}
Важно: переадресации в
beforeFiles
не проверяют файловую систему/динамические маршруты сразу после сопоставления source, они продолжают проверку, пока не будут проверены всеbeforeFiles
.
Порядок проверки маршрутов в Next.js:
- Проверяются/применяются headers
- Проверяются/применяются redirects
- Проверяются/применяются переадресации
beforeFiles
- Проверяются/обслуживаются статические файлы из публичной директории (public directory), файлы
_next/static
и нединамические страницы - Проверяются/применяются переадресации
afterFiles
— если одна из этих переадресаций совпадает, мы проверяем динамические маршруты/статические файлы после каждого совпадения - Проверяются/применяются переадресации
fallback
— они применяются перед отображением страницы 404 и после проверки всех динамических маршрутов/статических ресурсов. Если вы используете fallback: true/'blocking' вgetStaticPaths
, переадресацииfallback
, определённые вnext.config.js
, не будут выполнены.
Параметры переадресации
При использовании параметров в переадресации параметры по умолчанию передаются в запросе, если ни один из параметров не используется в destination
.
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // Параметр :path не используется здесь, поэтому будет автоматически передан в запросе
},
]
},
}
Если параметр используется в destination, ни один из параметров не будет автоматически передан в запросе.
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // Параметр :path используется здесь, поэтому не будет автоматически передан в запросе
},
]
},
}
Вы всё ещё можете передать параметры вручную в запросе, если один уже используется в destination, указав запрос в destination
.
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// Поскольку параметр :first используется в destination, параметр :second
// не будет автоматически добавлен в запрос, хотя мы можем добавить его вручную,
// как показано выше
},
]
},
}
Важно: Параметры статических страниц из Automatic Static Optimization или пререндеринга (prerendering) из переадресаций будут разобраны на клиенте после гидрации и предоставлены в запросе.
Сопоставление путей
Допускается сопоставление путей, например /blog/:slug
совпадёт с /blog/hello-world
(без вложенных путей):
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // Сопоставленные параметры могут использоваться в destination
},
]
},
}
Сопоставление путей с подстановочными знаками
Для сопоставления пути с подстановочными знаками вы можете использовать *
после параметра, например /blog/:slug*
совпадёт с /blog/a/b/c/d/hello-world
:
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // Сопоставленные параметры могут использоваться в destination
},
]
},
}
Сопоставление путей с регулярными выражениями
Для сопоставления пути с регулярным выражением вы можете обернуть регулярное выражение в скобки после параметра, например /blog/:slug(\\d{1,})
совпадёт с /blog/123
, но не с /blog/abc
:
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // Сопоставленные параметры могут использоваться в destination
},
]
},
}
Следующие символы (
, )
, {
, }
, [
, ]
, |
, \
, ^
, .
, :
, *
, +
, -
, ?
, $
используются для сопоставления путей с регулярными выражениями, поэтому при использовании в source
как обычные значения они должны быть экранированы добавлением \\
перед ними:
module.exports = {
async rewrites() {
return [
{
// это совпадёт с запросом `/english(default)/something`
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}
Сопоставление по заголовкам, кукам и запросам
Чтобы переадресация применялась только при совпадении значений заголовков, кук или запросов, можно использовать поле has
или поле missing
. И source
, и все элементы has
должны совпадать, а все элементы missing
не должны совпадать для применения переадресации.
Элементы has
и missing
могут иметь следующие поля:
type
:String
— должно бытьheader
,cookie
,host
илиquery
.key
:String
— ключ из выбранного типа для сопоставления.value
:String
илиundefined
— значение для проверки, если undefined, подойдёт любое значение. Можно использовать строку, подобную регулярному выражению, для захвата определённой части значения, например, если значениеfirst-(?<paramName>.*)
используется дляfirst-second
, тоsecond
можно будет использовать в destination как:paramName
.
module.exports = {
async rewrites() {
return [
// если присутствует заголовок `x-rewrite-me`,
// будет применена эта переадресация
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// если заголовок `x-rewrite-me` отсутствует,
// будет применена эта переадресация
{
source: '/:path*',
missing: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// если совпадают source, запрос и кука,
// будет применена эта переадресация
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// значение page не будет доступно в destination,
// так как value предоставлено и не использует именованную группу захвата,
// например (?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
destination: '/:path*/home',
},
// если присутствует заголовок `x-authorized`
// и содержит соответствующее значение, будет применена эта переадресация
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
destination: '/home?authorized=:authorized',
},
// если хост `example.com`,
// будет применена эта переадресация
{
source: '/:path*',
has: [
{
type: 'host',
value: 'example.com',
},
],
destination: '/another-page',
},
]
},
}
Переадресация на внешний URL
Переадресации позволяют перенаправлять на внешние URL. Это особенно полезно для постепенного внедрения Next.js. Ниже приведён пример переадресации для перенаправления маршрута /blog
вашего основного приложения на внешний сайт.
module.exports = {
async rewrites() {
return [
{
source: '/blog',
destination: 'https://example.com/blog',
},
{
source: '/blog/:slug',
destination: 'https://example.com/blog/:slug', // Сопоставленные параметры могут использоваться в destination
},
]
},
}
Если вы используете trailingSlash: true
, вам также нужно добавить завершающий слэш в параметр source
. Если целевой сервер также ожидает завершающий слэш, он должен быть включён в параметр destination
.
module.exports = {
trailingSlash: true,
async rewrites() {
return [
{
source: '/blog/',
destination: 'https://example.com/blog/',
},
{
source: '/blog/:path*/',
destination: 'https://example.com/blog/:path*/',
},
]
},
}
Постепенное внедрение Next.js
Вы также можете настроить Next.js на проксирование к существующему веб-сайту после проверки всех маршрутов Next.js.
Таким образом, вам не нужно изменять конфигурацию переадресаций при переносе большего количества страниц в Next.js.
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}
Переадресации с поддержкой basePath
При использовании basePath
с переадресациями каждый source
и destination
автоматически дополняется basePath
, если вы не добавите basePath: false
к переадресации:
module.exports = {
basePath: '/docs',
async rewrites() {
return [
{
source: '/with-basePath', // автоматически становится /docs/with-basePath
destination: '/another', // автоматически становится /docs/another
},
{
// не добавляет /docs к /without-basePath, так как установлено basePath: false
// Примечание: это нельзя использовать для внутренних переадресаций, например `destination: '/another'`
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
},
]
},
}
Переадресации с поддержкой i18n
При использовании i18n
с переадресациями каждый source
и destination
автоматически дополняется для обработки настроенных locales
, если вы не добавите locale: false
к переадресации. Если используется locale: false
, вы должны вручную добавить локаль к source
и destination
для правильного сопоставления.
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
async rewrites() {
return [
{
source: '/with-locale', // автоматически обрабатывает все локали
destination: '/another', // автоматически передаёт локаль
},
{
// не обрабатывает локали автоматически, так как установлено locale: false
source: '/nl/with-locale-manual',
destination: '/nl/another',
locale: false,
},
{
// это совпадёт с '/', так как `en` — defaultLocale
source: '/en',
destination: '/en/another',
locale: false,
},
{
// можно сопоставить все локали, даже если установлено locale: false
source: '/:locale/api-alias/:path*',
destination: '/api/:path*',
locale: false,
},
{
// это преобразуется в /(en|fr|de)/(.*), поэтому не совпадёт с корневыми
// маршрутами `/` или `/fr`, как это сделал бы /:path*
source: '/(.*)',
destination: '/another',
},
]
},
}
История версий
Версия | Изменения |
---|---|
v13.3.0 | Добавлен missing . |
v10.2.0 | Добавлен has . |
v9.5.0 | Добавлены заголовки. |