Next.js 16: qué cambió en performance

← Volver
Monitor con código fuente en editor dark theme, iluminación azul profesional para desarrollo web
Foto de Rob Wingate en Unsplash

Next.js 16 llegó en octubre de 2025 y es la versión más orientada a rendimiento desde que apareció el App Router. No es un lanzamiento incremental: tres cambios estructurales afectan directamente cómo se construyen y sirven las aplicaciones, y los tres tienen consecuencias medibles en Core Web Vitals. Este post los analiza uno a uno, con el impacto concreto que tienen y el criterio para decidir si merece la pena migrar ahora.

1. Turbopack estable: lo que cambia en el día a día

A partir de Next.js 16, Turbopack es estable y se usa por defecto tanto en next dev como en next build. Ya no hace falta la flag --turbopack. Si tienes en tu package.json scripts como next dev --turbopack o next build --turbopack, puedes eliminar esas flags: ya no son necesarias.

Turbopack ofrece builds de producción entre 2 y 5 veces más rápidos y Fast Refresh hasta 10 veces más rápido que Webpack. Para proyectos grandes, el impacto en el ciclo de desarrollo es inmediato. En CI, los builds más cortos se traducen en retroalimentación más rápida y menor coste de cómputo por pipeline.

La implicación directa en rendimiento de usuario final es más discreta pero existe: builds más rápidos permiten deploys más frecuentes, lo que facilita iterar sobre optimizaciones de performance sin que el coste operativo del pipeline sea un freno.

¿Y si tengo configuración personalizada de Webpack?

En Next.js 16, si tu proyecto tiene una configuración personalizada de Webpack, next build falla por defecto para evitar errores silenciosos de configuración. Tienes tres opciones: migrar la config a Turbopack, usar next build --turbopack para ignorar la config de Webpack, o usar next build --webpack para seguir con Webpack mientras completas la migración.

La mayoría de loaders populares (CSS Modules, SASS, optimización de imágenes) están integrados en Turbopack. Para el resto, el campo turbopack.rules en next.config.ts funciona como escape hatch.

Turbopack también introduce filesystem caching en modo desarrollo: almacena artefactos del compilador en disco entre reinicios, lo que acelera significativamente los tiempos de compilación en proyectos grandes. En Next.js 16.1 esta funcionalidad llegó a estable y se activa por defecto.

2. Cache Components y PPR: el cambio que más afecta al LCP

Este es el cambio más sustancial de Next.js 16 y el que tiene mayor impacto en Core Web Vitals, especialmente en LCP y TTFB.

Hasta ahora, la decisión de renderizar una ruta de forma estática o dinámica era binaria y se aplicaba a toda la página. Funciona en casos simples, pero se vuelve restrictivo a medida que la aplicación crece, porque la mayoría de páginas reales combinan datos predecibles con datos específicos de la petición.

Next.js 16 introduce Cache Components, un enfoque fundamentalmente nuevo que reemplaza el comportamiento implícito por un control explícito y composable. El modelo funciona así:

  • Marcas con la directiva 'use cache' los componentes o funciones de servidor cuyos datos quieres cachear.
  • Envuelves en <Suspense> el contenido dinámico que no se puede prerenderizar.

El shell estático se carga al instante mientras el contenido dinámico hace streaming. Obtienes lo mejor de los dos mundos: cargas iniciales rápidas con contenido personalizado.

Este modelo de renderizado se llama Partial Prerendering (PPR), y es el comportamiento por defecto cuando se activa cacheComponents.

En términos de Core Web Vitals, la diferencia práctica es clara: el shell estático de la página llega al navegador desde el edge sin esperar a ninguna petición de base de datos ni servicio externo. El LCP mejora porque el contenido principal puede formar parte de ese shell. El TTFB mejora porque el servidor no bloquea la respuesta inicial. El INP no se ve directamente afectado por el modelo de caché, pero sí indirectamente si antes tenías componentes que hacían fetching en el cliente bloqueando la interacción.

Cómo se configura

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig

Con cacheComponents: true activo, puedes usar 'use cache' en componentes de servidor y controlar el tiempo de vida de la caché con cacheLife() y la invalidación con cacheTag().

import { cacheLife } from 'next/cache'

async function ProductList() {
  'use cache'
  cacheLife('hours') // perfil de caché predefinido

  const products = await fetchProducts()
  return <ul>{products.map(p => <li key={p.id}>{p.name}</li>)}</ul>
}

El componente anterior se prerenderiza, se cachea durante horas y se sirve desde el edge. Si un producto cambia, puedes invalidarlo con cacheTag y revalidateTag sin esperar a que expire el tiempo de vida.

Next.js requiere que manejes explícitamente los componentes que no pueden completarse durante el prerenderizado. Si no los envuelves en <Suspense> ni los marcas con 'use cache', obtendrás un error en desarrollo y en tiempo de build.

¿Debo activar cacheComponents ahora?

Si usas export const revalidate = 60 en route segment files, eso sigue funcionando en Next.js 16 sin activar cacheComponents. Es el camino conservador: migrar a Turbopack (automático) y dejar la estrategia de caché para cuando hayas revisado los patrones de cada ruta.

Si decides activar cacheComponents, deberías migrar a 'use cache' con cacheLife(), porque la configuración de revalidación por route segment queda deprecada bajo el nuevo modelo.

3. proxy.ts: el reemplazo de middleware.ts

En Next.js 16, proxy.ts reemplaza a middleware.ts y hace explícito el límite de red de la aplicación. proxy.ts corre en el runtime de Node.js.

El cambio es más semántico que funcional para la mayoría de casos, pero tiene una implicación importante: el edge runtime no está soportado en proxy. Su runtime es Node.js y no puede configurarse. Si necesitas continuar usando el edge runtime, mantén middleware.ts.

La migración para quien no usa edge runtime es sencilla. El codemod oficial la automatiza:

npx @next/codemod@latest middleware-to-proxy

El codemod renombra el archivo y el nombre de la función de middleware a proxy. El resultado es equivalente a esto:

// Antes: middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

// Después: proxy.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export default function proxy(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

middleware.ts sigue funcionando en Next.js 16 pero está deprecado. La migración a proxy.ts es simple: renombrar el archivo y cambiar el nombre del export.

4. Otros cambios con impacto en rendimiento

React Compiler estable. React Compiler 1.0 llega con soporte integrado para memoización automática de componentes. Esta característica está estable. Reduce re-renders innecesarios sin requerir useMemo o useCallback manuales. Actívalo si tu app tiene problemas de rendimiento por re-renders excesivos. No lo actives si ya funciona bien y quieres builds más rápidos, porque el React Compiler añade overhead de compilación considerable. Prueba con y sin él para ver si las ganancias en runtime justifican el coste en build.

next/image y el cambio en images.qualities. Next.js 16 cambió images.qualities de [1..100] a [75] por defecto, lo que significa que el prop quality se redondea al valor más cercano del array. Si necesitas distintos niveles de calidad, debes configurar images.qualities explícitamente en next.config.ts. Esto reduce el número de variantes de imagen que Next.js genera, mejorando el rendimiento del build.

Routing mejorado. Las navegaciones son más rápidas gracias a la deduplicación de layouts y el prefetching incremental. En aplicaciones con muchos enlaces internos, esto reduce el coste de red en la precarga y mejora la percepción de velocidad durante la navegación.

params y searchParams ahora son estrictamente asíncronos. Next.js 15 introdujo la asincronía de estas APIs como breaking change, manteniendo una compatibilidad síncrona temporal. Next.js 16 elimina definitivamente ese acceso síncrono: solo pueden usarse de forma asíncrona. Al forzar este modelo, Next.js puede empezar a renderizar la página antes de que todos los params estén resueltos, mejorando el TTFB. El codemod de migración gestiona este cambio automáticamente en la mayoría de casos.

5. Cuándo migrar desde Next.js 15

La actualización desde Next.js 15 es directa porque la mayoría de cambios breaking los gestiona el codemod automáticamente. El comando es:

npx @next/codemod@latest upgrade latest

Dicho esto, hay tres situaciones donde conviene ir con calma:

Tienes webpack personalizado. Antes de migrar, audita tus loaders y plugins. Comprueba la tabla de compatibilidad de Turbopack para confirmar que todo tiene equivalente. Si algo no está soportado todavía, puedes mantener Webpack con --webpack mientras completas la migración progresivamente.

Usas middleware.ts con lógica de edge runtime. Si necesitas continuar con el edge runtime, mantén middleware.ts. La documentación oficial indica que publicarán instrucciones adicionales en una minor release.

Tienes cacheComponents activo o PPR experimental. Como se explicó antes, este path requiere revisión manual de la estrategia de caché por ruta. No es algo que resuelva el codemod.

Si estás empezando un proyecto nuevo, Next.js 16 es estable y listo para producción. Para aplicaciones existentes, revisa primero los cambios breaking.


Si estás evaluando si tu stack actual está bien posicionado para aprovechar estas mejoras —o si hay otros cuellos de botella que resolverlos antes tiene más impacto que migrar de versión—, puedes ver cómo trabajo la auditoría técnica antes de tomar ninguna decisión.