Next.js 16 New Features: Turbopack por Defecto y el App Router Que Ya Manda — Arquitectura Antes que Velocidad

Next.js 16 New Features: Turbopack por Defecto y el App Router Que Ya Manda — Arquitectura Antes que Velocidad

Programming· 8 min read

La feature más importante de Next.js 16 no es nueva. Se desplegó en octubre de 2022

En 2022, Next.js invirtió silenciosamente React.

Cada componente que escribes es ahora un Server Component por defecto. La ejecución en cliente es la excepción, no la regla. Y el fetch dentro de useEffect —el patrón que alimentó los últimos cinco años de apps React— se ha convertido en el mayor motivo de que tu Next.js vaya lento.

Cuando la gente busca "nextjs 16 new features", espera una lista de funciones. Velocidades de build. Turbopack. Pero la historia real no es esa.

*El problema no es que Next.js vaya lento. Es que tu arquitectura decide que vaya lento. *

Desde Next.js 13 (octubre de 2022), el App Router invirtió el modelo mental de React: la ejecución en servidor es el default y optas fuera con 'use client' en el borde interactivo. La mayoría de los que reportan "migramos y fue más lento" todavía escriben React client-first: fetch en useEffect, caching desactivado globalmente, lecturas de cookies que fuerzan toda la ruta a dinámica.

¿Qué trae de verdad Next.js 16? Turbopack como bundler por defecto para dev y production builds. Escrito en Rust. Fue el sustituto de webpack. Y los async request APIs que Next.js 15 (octubre 2024) introdujo —cookies(), headers(), params, searchParams ahora se hacen con await— rompen middlewares y Server Actions escritos con el patrón antiguo.

Pero nada de eso importa si sigues arquitectando con el manual de 2020.

El problema: estás arquitectando un framework nuevo con hábitos viejos

En el Pages Router (antes de Next.js 13), el render en servidor era una elección explícita. Escribías getServerSideProps si querías SSR. El resto era cliente. La lógica de render estaba clara: todo cliente, a menos que digas lo contrario.

El App Router lo invierte por completo: todo servidor, a menos que escribas `'use client'`. Dos mentalidades opuestas que conviven en el mismo ecosistema.

¿Qué pasa cuando un equipo migra sin cambiar la mentalidad? Esto:

useEffect que hace fetch de datos tras el primer render (doble render, doble round trip)

❌ Desactivar cache globalmente con export const dynamic = 'force-dynamic' porque "los datos cambian a menudo"

❌ Leer cookies() en una ruta estática para cambiar un texto de entrada — convirtiendo toda la ruta en dinámica

❌ Componentes que acceden a window o document sin envoltorio de cliente — error en el server

fetch directo en un Server Component async

✅ Props serializables hacia abajo, 'use client' solo en la hoja interactiva

revalidate explícito por ruta, no force-dynamic global

✅ Envoltorio cliente mínimo para librerías que tocan APIs del navegador

La migración del Pages Router al App Router no es un rename de carpetas. Es un cambio de arquitectura con costes operativos propios. Un team que migra el código sin migrar el modelo mental no está usando Next.js 16. Está pagando por él.

La evidencia: tres cambios concretos que ya están aquí

1. Turbopack es el bundler por defecto

Next.js 16 hizo de Turbopack el bundler por defecto para development y production builds. Escrito en Rust, reemplaza a webpack como ruta principal. Los cold starts y rebuilds aceleran de forma dramática.

El matiz que la mayoría ignora: algunos plugins y configs de webpack necesitan rework. Si tu proyecto se apoya en loaders webpack personalizados, la checklist de migración de build importa tanto como las features de runtime. No es solo "actualiza y listo".

2. Las Async Request APIs rompen medio ecosistema

Next.js 15 hizo asíncronas las APIs de petición. cookies(), headers(), params y searchParams ahora requieren await.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

No es un cambio cosmético. Rompe middlewares, librerías de autenticación y Server Actions que usaban el patrón sincrónico. Es el segundo mayor motivo de "dos semanas perdidas" en equipos que migran.

3. El Server Component como default: fetch sin useEffect

Este es el cambio que más se malinterpreta. En el Pages Router, esto era el patrón estándar:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

En el App Router, el reemplazo es directo — sin estado, sin efecto, sin round trip extra:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

El Server Component se ejecuta en el servidor una vez, pinta HTML y envía props serializables a las hojas interactivas. No hay hidratación de datos. No hay "loading spinner de datos que podría ya tener".

Análisis: por qué "Next.js va lento" es un síntoma, no el diagnóstico

El App Router cachea agresivamente en build time por defecto. Pero una sola lectura de `cookies()` o `headers()` marca toda la ruta como dinámica.

Este es el detalle que te ahorra horas de debugging:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Añadir middleware de autenticación o leer una cookie mata el ISR y el render estático de todo el segmento de ruta. La mayoría de equipos no lo saben hasta que las métricas de cache caen en picado sin tocar nada.

El que dice "Next.js 16 va lento" casi siempre tiene esto: fetch en useEffect, force-dynamic global, o una cookie leída en la raíz que dinámiza todo el árbol. No es Next.js. Es tu arquitectura.

Y el trade-off honesto: gran parte del pulido del App Router —tuner de ISR, Edge runtime, optimización de imágenes— está optimizado para la plataforma de Vercel. El self-hosting está soportado, pero algunos ergonomics se degradan. Para un equipo con infraestructura propia, esa es una decisión arquitectónica real, no cheerleading.

El Marco de 5 Rutas para Auditoría del App Router

Un framework que no invento sobre la marcha: el patrón que aplico en cada migración que hago. Cinco pasos, en orden.

Ruta 1: Audita el render por ruta antes de escribir código

Ve ruta por ruta y decide: ¿estática, dinámica o ISR? No defaults dinámico porque tu app vieja usaba getServerSideProps en todo. El 80% de las páginas de contenido probablemente son estáticas o ISR.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Ruta 2: Mueve el fetch arriba del árbol

Todo fetch a datos que no cambian por usuario debe vivir en un Server Component async. Props serializables hacia abajo. 'use client' solo en la hoja interactiva.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

La hoja interactiva sigue corriendo 100% en el cliente. No es una red de round trips por click. El borde es tuyo: elígelo donde haga falta.

Ruta 3: Adopta el streaming deliberadamente

Envuelve llamadas lentas a bases de datos o APIs terceras en <Suspense> para que el shell pinte de inmediato y lo lento streamee después.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Trata los ficheros loading.tsx como el skeleton por defecto. Es gratis y da una experiencia inmediata.

Ruta 4: Conoce los disparadores de cache

Aprende qué APIs (cookies(), headers(), searchParams) te optan automáticamente a render dinámico. Y define `revalidate` de forma explícita por ruta, nunca desactives cache globalmente.

Ruta 5: Migra por etapas desde Pages Router

Convierte de forma incremental usando route groups. Mantén ambos routers funcionando durante la transición. Migra primero las páginas de más tráfico para medir el impacto real antes de tocar el resto.

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

La fricción número uno que casi nadie te avisa: el ecosistema

Cuando reportan "está roto", casi siempre es esto: librerías terceras que tocan `window`, `document` u otras APIs client-only lanzan error en Server Components.

La solución es un patrón pequeño pero que te ahorra dos semanas:

[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Ese patrón es el mayor punto de fricción práctico al adoptar el App Router. Conócelo antes de encontrarlo en producción.

¿Sigue teniendo sentido quedarse en el Pages Router?

Sí. Es una decisión legítima. Si tu app funciona, tus métricas de Core Web Vitals son buenas y no necesitas streaming ni ISR fino, quedarte es una opción razonable.

Pero entiende lo que estás aceptando: el App Router no es un rename. Es otro framework con costes operativos distintos. Si migras, migra el modelo mental con el código. Si no migras, no migres a medias.

Conclusión: la arquitectura antes que la feature

Las new features de Next.js 16 —Turbopack por defecto, Async Request APIs, Server Components como estándar— no te van a hacer rápido por sí solas. Tu arquitectura decide si Next.js va rápido o va lento.

Cuando en 2024 Vercel presentó el App Router con el binario estático vs dinámico, pocos entendieron la factura. Hoy, con Turbopack acelerando builds y el modelo de Server Components maduro, la decisión es clara: aprende el modelo invertido o paga el impuesto de la lógica old-school en cada deploy.

La feature más rentable de Next.js 16 no está en las release notes. Es entender que desde octubre de 2022, todo componente es un Server Component por defecto. Y tu useEffect con fetch dentro ya no es el patrón — es el problema.

Artículos relacionados

---

¿Quieres recibir contenido como este cada semana? Suscríbete a mi newsletter

Brian Mena

Brian Mena

Software engineer building profitable digital products: SaaS, directories and AI agents. All from scratch, all in production.

LinkedIn