rewrites
Переадресация (rewrites) позволяет сопоставить входящий путь запроса с другим целевым путем.
Переадресация действует как URL-прокси и маскирует целевой путь, создавая впечатление, что пользователь не изменил свое местоположение на сайте. В отличие от этого, редиректы перенаправляют на новую страницу и показывают изменения 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
) и перед динамическими маршрутами. Начиная с версии v10.1
Next.js, когда функция rewrites
возвращает объект с массивами определенной структуры, это поведение можно изменить и более тонко контролировать:
module.exports = {
async rewrites() {
return {
beforeFiles: [
// Эти переадресации проверяются после headers/redirects
// и перед всеми файлами, включая _next/public, что
// позволяет переопределять файлы страниц
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// Эти переадресации проверяются после проверки pages/public файлов,
// но перед динамическими маршрутами
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// Эти переадресации проверяются после проверки pages/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
, не будут выполнены.
Параметры переадресации
При использовании параметров в переадресации параметры по умолчанию передаются в query, если ни один из параметров не используется в destination
.
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // Параметр :path здесь не используется, поэтому будет автоматически передан в query
},
]
},
}
Если параметр используется в destination, ни один из параметров не будет автоматически передан в query.
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // Параметр :path используется здесь, поэтому не будет автоматически передан в query
},
]
},
}
Вы все равно можете передать параметры в query вручную, если один из них уже используется в destination, указав query в destination
.
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// Поскольку параметр :first используется в destination, параметр :second
// не будет автоматически добавлен в query, но мы можем добавить его вручную,
// как показано выше
},
]
},
}
Полезно знать: Параметры из переадресации для статических страниц, созданных с помощью Automatic Static Optimization или prerendering, будут разобраны на клиенте после гидрации и предоставлены в query.
Сопоставление путей
Допускается сопоставление путей, например /blog/:slug
совпадет с /blog/hello-world
(без вложенных путей):
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // Сопоставленные параметры могут использоваться в destination
},
]
},
}
Сопоставление с использованием wildcard
Для сопоставления с wildcard можно использовать *
после параметра, например /blog/:slug*
совпадет с /blog/a/b/c/d/hello-world
:
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // Сопоставленные параметры могут использоваться в destination
},
]
},
}
Сопоставление с использованием регулярных выражений
Для сопоставления с регулярным выражением можно заключить regex в скобки после параметра, например /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',
},
]
},
}
Сопоставление по заголовкам, cookies и query
Чтобы переадресация применялась только при совпадении значений заголовков, cookies или query, можно использовать поле has
или missing
. Для применения переадресации должны совпадать и source
, и все элементы has
, а также не должны совпадать все элементы missing
.
Элементы has
и missing
могут иметь следующие поля:
type
:String
— должно бытьheader
,cookie
,host
илиquery
.key
:String
— ключ из выбранного типа для сопоставления.value
:String
илиundefined
— значение для проверки; если undefined, подойдет любое значение. Можно использовать строку, похожую на regex, для захвата части значения, например, если значение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, query и cookie,
// будет применена эта переадресация
{
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',
},
// если host — `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 | Добавлены заголовки. |