Redirecciones
Las redirecciones permiten redirigir una ruta de solicitud entrante a una ruta de destino diferente.
Para usar redirecciones, puedes utilizar la clave redirects
en next.config.js
:
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true,
},
]
},
}
redirects
es una función asíncrona que espera que se devuelva un array con objetos que contengan las propiedades source
, destination
y permanent
:
source
: es el patrón de ruta de la solicitud entrante.destination
: es la ruta a la que deseas redirigir.permanent
:true
ofalse
- si estrue
usará el código de estado 308 que indica a los clientes/motores de búsqueda que almacenen en caché la redirección permanentemente, si esfalse
usará el código de estado 307 que es temporal y no se almacena en caché.
¿Por qué Next.js usa 307 y 308? Tradicionalmente se usaba 302 para redirecciones temporales y 301 para permanentes, pero muchos navegadores cambiaban el método de solicitud de la redirección a
GET
, independientemente del método original. Por ejemplo, si el navegador hacía una solicitudPOST /v1/users
que devolvía código de estado302
con ubicación/v2/users
, la solicitud posterior podría serGET /v2/users
en lugar delPOST /v2/users
esperado. Next.js usa los códigos de estado 307 (temporal) y 308 (permanente) para preservar explícitamente el método de solicitud utilizado.
basePath
:false
oundefined
- si es false, elbasePath
no se incluirá al hacer coincidencias, solo puede usarse para redirecciones externas.locale
:false
oundefined
- indica si no se debe incluir la configuración regional al hacer coincidencias.has
: es un array de objetos has con las propiedadestype
,key
yvalue
.missing
: es un array de objetos missing con las propiedadestype
,key
yvalue
.
Las redirecciones se verifican antes del sistema de archivos, que incluye páginas y archivos /public
.
Cuando se usa el Enrutador de Páginas, las redirecciones no se aplican al enrutamiento del lado del cliente (Link
, router.push
) a menos que esté presente un Middleware y coincida con la ruta.
Cuando se aplica una redirección, cualquier valor de consulta proporcionado en la solicitud se pasará a la ruta de destino. Por ejemplo, observa la siguiente configuración de redirección:
{
source: '/old-blog/:path*',
destination: '/blog/:path*',
permanent: false
}
Cuando se solicita /old-blog/post-1?hello=world
, el cliente será redirigido a /blog/post-1?hello=world
.
Coincidencia de Rutas
Se permiten coincidencias de rutas, por ejemplo /old-blog/:slug
coincidirá con /old-blog/hello-world
(sin rutas anidadas):
module.exports = {
async redirects() {
return [
{
source: '/old-blog/:slug',
destination: '/news/:slug', // Los parámetros coincidentes pueden usarse en el destino
permanent: true,
},
]
},
}
Coincidencia de Rutas con Comodín
Para coincidir con una ruta comodín puedes usar *
después de un parámetro, por ejemplo /blog/:slug*
coincidirá con /blog/a/b/c/d/hello-world
:
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // Los parámetros coincidentes pueden usarse en el destino
permanent: true,
},
]
},
}
Coincidencia de Rutas con Expresiones Regulares
Para coincidir con una ruta usando expresiones regulares, puedes envolver la regex entre paréntesis después de un parámetro, por ejemplo /post/:slug(\\d{1,})
coincidirá con /post/123
pero no con /post/abc
:
module.exports = {
async redirects() {
return [
{
source: '/post/:slug(\\d{1,})',
destination: '/news/:slug', // Los parámetros coincidentes pueden usarse en el destino
permanent: false,
},
]
},
}
Los siguientes caracteres (
, )
, {
, }
, :
, *
, +
, ?
se usan para coincidencias de rutas con regex, por lo que cuando se usan en source
como valores no especiales deben escaparse agregando \\
antes:
module.exports = {
async redirects() {
return [
{
// esto coincidirá con `/english(default)/something` cuando se solicite
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
permanent: false,
},
]
},
}
Coincidencia de Encabezados, Cookies y Consultas
Para que una redirección coincida solo cuando los valores de encabezado, cookie o consulta también coincidan, se puede usar el campo has
o missing
. Tanto el source
como todos los elementos has
deben coincidir, y todos los elementos missing
no deben coincidir para que se aplique la redirección.
Los elementos has
y missing
pueden tener los siguientes campos:
type
:String
- debe serheader
,cookie
,host
oquery
.key
:String
- la clave del tipo seleccionado con la que coincidir.value
:String
oundefined
- el valor a verificar, si es undefined cualquier valor coincidirá. Se puede usar una cadena tipo regex para capturar una parte específica del valor, por ejemplo, si se usa el valorfirst-(?<paramName>.*)
parafirst-second
, entoncessecond
será utilizable en el destino con:paramName
.
module.exports = {
async redirects() {
return [
// si el encabezado `x-redirect-me` está presente,
// se aplicará esta redirección
{
source: '/:path((?!another-page$).*)',
has: [
{
type: 'header',
key: 'x-redirect-me',
},
],
permanent: false,
destination: '/another-page',
},
// si el encabezado `x-dont-redirect` está presente,
// NO se aplicará esta redirección
{
source: '/:path((?!another-page$).*)',
missing: [
{
type: 'header',
key: 'x-do-not-redirect',
},
],
permanent: false,
destination: '/another-page',
},
// si coinciden el source, la consulta y la cookie,
// se aplicará esta redirección
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// el valor page no estará disponible en el
// destino ya que se proporciona value y no
// usa un grupo de captura nombrado, ej. (?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
permanent: false,
destination: '/another/:path*',
},
// si el encabezado `x-authorized` está presente y
// contiene un valor coincidente, se aplicará esta redirección
{
source: '/',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
permanent: false,
destination: '/home?authorized=:authorized',
},
// si el host es `example.com`,
// se aplicará esta redirección
{
source: '/:path((?!another-page$).*)',
has: [
{
type: 'host',
value: 'example.com',
},
],
permanent: false,
destination: '/another-page',
},
]
},
}
Redirecciones con soporte para basePath
Cuando se usa basePath
con redirecciones, cada source
y destination
se prefija automáticamente con el basePath
a menos que agregues basePath: false
a la redirección:
module.exports = {
basePath: '/docs',
async redirects() {
return [
{
source: '/with-basePath', // automáticamente se convierte en /docs/with-basePath
destination: '/another', // automáticamente se convierte en /docs/another
permanent: false,
},
{
// no agrega /docs ya que se establece basePath: false
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
permanent: false,
},
]
},
}
Redirecciones con soporte para i18n
Cuando se usa i18n
con redirecciones, cada source
y destination
se prefija automáticamente para manejar los locales
configurados a menos que agregues locale: false
a la redirección. Si se usa locale: false
, debes prefijar source
y destination
con un locale para que coincida correctamente.
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
async redirects() {
return [
{
source: '/with-locale', // maneja automáticamente todos los locales
destination: '/another', // pasa automáticamente el locale
permanent: false,
},
{
// no maneja locales automáticamente ya que se establece locale: false
source: '/nl/with-locale-manual',
destination: '/nl/another',
locale: false,
permanent: false,
},
{
// esto coincide con '/' ya que `en` es el defaultLocale
source: '/en',
destination: '/en/another',
locale: false,
permanent: false,
},
// es posible coincidir con todos los locales incluso cuando locale: false está establecido
{
source: '/:locale/page',
destination: '/en/newpage',
permanent: false,
locale: false,
},
{
// esto se convierte a /(en|fr|de)/(.*) por lo que no coincidirá con las rutas
// de nivel superior `/` o `/fr` como lo haría /:path*
source: '/(.*)',
destination: '/another',
permanent: false,
},
]
},
}
En algunos casos raros, es posible que necesites asignar un código de estado personalizado para que los clientes HTTP antiguos redirijan correctamente. En estos casos, puedes usar la propiedad statusCode
en lugar de permanent
, pero no ambas. Para garantizar la compatibilidad con IE11, se agrega automáticamente un encabezado Refresh
para el código de estado 308.
Otras Redirecciones
- Dentro de API Routes y Route Handlers, puedes redirigir según la solicitud entrante.
- Dentro de
getStaticProps
ygetServerSideProps
, puedes redirigir páginas específicas en tiempo de solicitud.
Historial de Versiones
Versión | Cambios |
---|---|
v13.3.0 | Se agregó missing . |
v10.2.0 | Se agregó has . |
v9.5.0 | Se agregó redirects . |