tutoriales.com

Creando Middleware Personalizado y Avanzado en Next.js App Router 🚀

Domina el uso de Middleware en Next.js para interceptar solicitudes a nivel de servidor antes de que se completen. Mejora la seguridad, gestiona autenticaciones complejas y optimiza la redirección de usuarios.

Avanzado8 min de lectura5 views
Reportar error

Introducción al Middleware en Next.js ⚡

El Middleware en Next.js es una potente herramienta que te permite ejecutar código antes de que una petición sea completada. A medida que tus aplicaciones web crecen, la necesidad de interceptar peticiones para verificar la autenticación, aplicar redirecciones basadas en geolocalización o modificar cabeceras HTTP se vuelve fundamental. Con el App Router, el middleware se configura de manera centralizada y opera en el Edge Runtime, garantizando una latencia mínima.

💡 Consejo: El middleware se ejecuta para cada ruta en tu proyecto por defecto, por lo que es crucial configurar correctamente el matcher para evitar ejecuciones innecesarias en archivos estáticos o imágenes.

¿Cómo Funciona el Ciclo de Vida del Middleware? 🔄

Antes de escribir código, es importante comprender en qué momento entra en juego el middleware dentro del ciclo de solicitud y respuesta de Next.js. Cuando un usuario intenta acceder a una ruta, el middleware intercepta la petición HTTP, evalúa las condiciones programadas y decide si permite el acceso, si redirige al usuario a otra URL, o si reescribe el destino.

Petición del Usuario Next.js Framework middleware.ts ¿Cumple las condiciones? Permitir Acceso Ruta Destino Redirigir Página de Login Bloquear 403 Prohibido

Características Clave del Edge Runtime

  • Ejecución ultrarrápida cercana al usuario.
  • Limitaciones de Node.js (no puedes usar todos los módulos nativos como fs).
  • Soporte para APIs Web estándar como Request, Response, y fetch.

Configuración Inicial y Estructura del Archivo 🛠️

Para implementar un middleware en tu proyecto de Next.js, debes crear un archivo llamado exactamente middleware.ts (o middleware.js) en la raíz de tu proyecto, al mismo nivel que la carpeta app o pages. No lo coloques dentro de la carpeta app.

Veamos un ejemplo básico de la estructura inicial que captura todas las peticiones y simplemente permite que continúen su curso:

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  return NextResponse.next()
}

export const config = {
  matcher: '/about/:path*',
}

Explicación del Matcher

El objeto config con la propiedad matcher te permite especificar exactamente qué rutas deben activar este middleware. Puedes usar rutas exactas, comodines o expresiones regulares avanzadas.

📌 Nota: Si omites la configuración del matcher, el middleware se ejecutará en cada ruta de tu aplicación, incluyendo recursos estáticos, lo cual puede degradar el rendimiento.

Caso Práctico 1: Autenticación y Protección de Rutas 🔒

Uno de los usos más comunes del middleware es verificar si un usuario cuenta con una cookie de sesión válida antes de permitirle acceder a un panel de administración.

Imagina que tenemos una ruta /dashboard que solo debe ser accesible para usuarios autenticados. Si no existe la cookie de sesión, redirigiremos al usuario a la página de inicio de sesión.

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const sessionCookie = request.cookies.get('session_token')

  if (!sessionCookie) {
    const loginUrl = new URL('/login', request.url)
    loginUrl.searchParams.set('from', request.nextUrl.pathname)
    return NextResponse.redirect(loginUrl)
  }

  return NextResponse.next()
}

export const config = {
  matcher: '/dashboard/:path*',
}
⚠️ Advertencia: El middleware es ideal para comprobaciones rápidas de tokens o cookies, pero para validaciones de bases de datos pesadas o lógica de negocio compleja, es mejor realizar dichas comprobaciones dentro de los componentes del servidor o Server Actions.

Caso Práctico 2: Redirección Basada en Geolocalización e Idioma 🌍

Next.js facilita la detección de la ubicación geográfica del usuario a través de las cabeceras que inyecta Vercel (o plataformas compatibles con el Edge Runtime). Podemos usar esto para redirigir automáticamente a los usuarios a la versión de su idioma correspondiente.

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const country = request.geo?.country || 'US'
  const currentPath = request.nextUrl.pathname

  // Si el usuario está en la raíz y es de España, redirigir a /es
  if (currentPath === '/' && country === 'ES') {
    return NextResponse.redirect(new URL('/es', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: '/',
}

Modificando Cabeceras y Añadiendo Seguridad HTTP 🛡️

Otra funcionalidad excelente del middleware es la capacidad de modificar las cabeceras de respuesta o solicitud. Esto es muy útil para implementar políticas de seguridad (CSP), añadir identificadores de seguimiento (request IDs) o configurar CORS.

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const response = NextResponse.next()

  // Añadir cabeceras de seguridad personalizadas
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-Content-Type-Options', 'nosniff')
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')

  // Añadir un identificador único a cada petición
  const requestId = crypto.randomUUID()
  response.headers.set('X-Request-Id', requestId)

  return response
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

Buenas Prácticas y Rendimiento en el Edge 🚀

Para asegurarte de que tu middleware no se convierta en un cuello de botella, sigue estas recomendaciones:

1. Matchers específicos: Excluye siempre archivos estáticos, imágenes y rutas de API que no requieran procesamiento en el middleware.
2. Evita consultas pesadas: No realices conexiones directas a bases de datos relacionales pesadas desde el middleware en el Edge.
3. Mantén el código ligero: Utiliza librerías compatibles con Edge Runtime (como `jose` para JWT en lugar de librerías tradicionales de Node.js).

Preguntas Frecuentes (FAQ) 📖

¿Puedo usar bases de datos en el Middleware?Puedes usar bases de datos que ofrezcan APIs HTTP o drivers compatibles con Edge (como Edge Config o bases de datos con soporte HTTP), pero no drivers tradicionales de bases de datos que dependan de sockets TCP de Node.js.
¿Cómo depuro errores en el Middleware?Puedes utilizar console.log() dentro de tu función middleware. Los registros aparecerán en la terminal de desarrollo local y en los logs de producción de tu plataforma de despliegue como Vercel.
¿El middleware afecta el SEO?Si configuras redirecciones incorrectas o bloqueas bots de búsqueda por error, sí puede afectar negativamente. Asegúrate de excluir los user-agents de motores de búsqueda si aplicas restricciones estrictas.

Conclusión y Próximos Pasos 🎉

Has aprendido a implementar un middleware avanzado en Next.js App Router, desde la protección de rutas mediante cookies hasta la inyección de cabeceras de seguridad y redirecciones geográficas. El middleware es una herramienta indispensable para llevar tus aplicaciones web al siguiente nivel de robustez y seguridad.

Para seguir practicando, te sugiero integrar una validación de tokens JWT utilizando la librería jose dentro de tu middleware y experimentar combinando múltiples condiciones de redirección.

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!