App Router vs Pages Router: ¿Cuál elegir?

Lectura
20 min~10 min lectura
App Router vs Pages Router: ¿Cuál elegir?
CONCEPTO CLAVE: Next.js ofrece dos sistemas de enrutamiento principales: el Pages Router (tradicional, basado en el directorio `/pages`) y el App Router (moderno, basado en el directorio `/app` con React Server Components). Elegir correctamente entre ellos impacta directamente en el rendimiento, la experiencia de desarrollo y las capacidades de tu aplicación. Desde Next.js 13, el App Router es la opción recomendada oficialmente, pero el Pages Router sigue siendo válido para proyectos existentes.

🔍 ¿Qué es un Router en Next.js?

Un router es el sistema que determina cómo se manejan las URLs de tu aplicación y qué componentes se renderizan cuando el usuario accede a una ruta específica. En Next.js, cada archivo dentro de las carpetas de routing corresponde automáticamente a una ruta en tu aplicación. Por ejemplo, si creas un archivo about.js dentro de /pages, este será accesible en /about.

El router es fundamental porque define la estructura de navegación, los layouts (diseños compartidos), la gestión de estados de carga y la optimización del rendimiento de tu aplicación. Elegir el router adecuado desde el inicio de un proyecto te ahorrará refactorizaciones costosas más adelante.

📂 Pages Router: El Enfoque Tradicional

El Pages Router ha sido el sistema de enrutamiento de Next.js desde sus inicios. Utiliza el directorio /pages donde cada archivo representa una ruta. Este enfoque es intuitivo y fácil de entender: simplemente creas archivos y obtienes rutas automáticamente.

Características principales del Pages Router:

  • Enrutamiento basado en archivos: Cada archivo .js, .jsx, .ts o .tsx en /pages se convierte en una ruta.
  • Renderizado del lado del cliente por defecto: Usa React hooks como useEffect y useState directamente.
  • API Routes integrada: Puedes crear endpoints de API en /pages/api.
  • getServerSideProps: Para renderizado del lado del servidor por solicitud.
  • getStaticProps: Para generación estática en tiempo de compilación.
  • getStaticPaths: Para generación de rutas estáticas dinámicas.
// pages/index.js
export default function Home() {
  return (
    
      

Bienvenido a mi sitio

Usando Pages Router

); } // pages/about.js export default function About() { return (

Acerca de nosotros

Página estática con Pages Router

); } // pages/blog/[slug].js - Ruta dinámica export default function BlogPost({ post }) { return (

{post.title}

{post.content}

); } export async function getStaticPaths() { const posts = await fetchPosts(); return { paths: posts.map((post) => ({ params: { slug: post.slug }, })), fallback: false, }; } export async function getStaticProps({ params }) { const post = await fetchPostBySlug(params.slug); return { props: { post } }; }

🆕 App Router: La Nueva Era del Enrutamiento

El App Router (introducido en Next.js 13 como beta y estabilizado en Next.js 14) revoluciona la forma de construir aplicaciones. Utiliza el directorio /app y aprovecha los React Server Components (RSC), permitiendo renderizado híbrido y optimizado.

Características principales del App Router:

  • React Server Components: Los componentes se renderizan en el servidor por defecto, reduciendo el JavaScript enviado al cliente.
  • Nested Layouts: Permite crear diseños anidados que persisten entre navegaciones sin recargar la página.
  • Streaming: Soporte nativo para Suspense y streaming de HTML.
  • Server Actions: Funciones que se ejecutan en el servidor y pueden ser llamadas desde el cliente.
  • Loading.js y Error.js: Archivos especiales para estados de carga y errores por ruta.
  • Mejor manejo de datos: Patrones más limpios para obtener ymutar datos.
// app/layout.js - Layout raíz
export default function RootLayout({ children }) {
  return (
    
      
        
          Inicio
          Acerca de
        
        {children}
      
    
  );
}

// app/page.js - Página de inicio
export default function Home() {
  return (
    
      

Bienvenido a mi sitio

Usando App Router con React Server Components

); } // app/blog/[slug]/page.js - Ruta dinámica export default async function BlogPost({ params }) { const post = await fetchPostBySlug(params.slug); return (

{post.title}

{post.content}

); } // app/blog/[slug]/loading.js - Estado de carga export default function Loading() { return
Cargando artículo...
; } // app/blog/[slug]/error.js - Manejo de errores export default function Error({ error }) { return
Error: {error.message}
; } // app/api/posts/route.js - API Route (opcional en App Router) export async function GET() { const posts = await fetchPosts(); return Response.json(posts); } // app/actions.js - Server Actions export async function createPost(formData) { 'use server'; const title = formData.get('title'); await savePost({ title }); revalidatePath('/blog'); }
💡 Tip práctico: Si estás migrando de Pages Router a App Router, puedes usar ambos simultáneamente en un proyecto. Next.js permite tener /pages y /app coexistiendo, aunque esto no es recomendado para nuevos proyectos. La carpeta /app tiene prioridad sobre /pages.

⚡ Comparación Detallada: Pages Router vs App Router

Característica Pages Router App Router
Directorio /pages /app
Renderizado por defecto Cliente (CSR) Servidor (RSC)
Componentes de servidor No disponibles Soportados nativamente
Obtención de datos getStaticProps, getServerSideProps async/await directo en componentes
Layouts anidados Limitado (usando _app.js) Native y flexibles
Manejo de estados de carga Componentes Loading convencionales loading.js por ruta
Server Actions No disponibles Soportadas
Tamaño del bundle Mayor (más JavaScript al cliente) Menor (server components no se envían)
Caché de datos Configuración manual Configuración simple con fetch
Middleware Requiere configuración adicional Integrado con matcher
SEO Bueno para páginas estáticas Mejorado con server components
Curva de aprendizaje Baja Moderada (nuevos conceptos)

🎯 ¿Cuándo Usar Cada Router?

Usa el Pages Router cuando:

  1. Proyecto existente: Ya tienes una aplicación funcionando con Pages Router y migrar sería costoso.
  2. Simplicidad requerida: Tu equipo está más familiarizado con React tradicional y hooks.
  3. Prototipado rápido: Necesitas crear un prototipo funcional rápidamente sin aprender nuevos patrones.
  4. Recursos educativos limitados: Documentación o tutoriales específicos para Pages Router son más abundantes.
  5. Requisitos de middleware complejos: Ya tienes middleware configurado que迁移 sería problemático.

Usa el App Router cuando:

  1. Nuevo proyecto: Estás iniciando una aplicación desde cero.
  2. Rendimiento óptimo: Necesitas el menor tamaño de bundle posible.
  3. Acceso a base de datos directo: Quieres consultar APIs o bases de datos directamente en componentes.
  4. Experiencia de usuario fluida: Necesitas layouts persistentes y transiciones suaves.
  5. Server Actions: Quieresmutaciones de datos sin crear endpoints API separados.
  6. Preparación para el futuro: Quieres usar las últimas características de React y Next.js.
⚠️ Error común: Muchos desarrolladores eligen Pages Router simplemente porque "es el que conocen" sin considerar las ventajas del App Router. Esto puede resultar en aplicaciones con peor rendimiento y más código redundante a largo plazo. Si estás comenzando un proyecto nuevo, siempre elige App Router a menos que tengas razones específicas para lo contrario.
Expandir: Migración paso a paso de Pages Router a App Router

Si decides migrar tu proyecto existente, aquí te explico el proceso general:

  1. Crea el directorio /app: Añade /app junto a tu /pages existente.
  2. Mueve tus componentes: Copia cada página de /pages a /app con el mismo nombre.
  3. Convierte getServerSideProps: Convierte a async/await directo en el componente.
  4. Convierte getStaticProps: Usa fetch con opciones de cache o async/await directo.
  5. Refactoriza _app.js: Crea /app/layout.js con el contenido del layout raíz.
  6. Mueve _document.js: Usa /app/layout.js con el HTML completo.
  7. Actualiza API routes: Mueve a /app/api/[ruta]/route.js con handlers GET, POST, etc.
  8. Añade archivos especiales: Crea loading.js, error.js donde sea necesario.
  9. Prueba exhaustivamente: Verifica cada ruta y funcionalidad.
  10. Elimina /pages: Una vez todo funcione, elimina el directorio /pages.

Durante la migración, puedes ejecutar ambos routers simultáneamente para validar funcionalidades incrementalmente.

Expandir: Profundizando en React Server Components

Los React Server Components (RSC) son una de las características más revolucionarias del App Router. Aquí algunos puntos clave:

  • Ejecución en servidor: Los Server Components se ejecutan solo en el servidor, enviando HTML al cliente.
  • Acceso directo a datos: Pueden hacerfetch a bases de datos o APIs internamente sin exponer credenciales.
  • Tamaño de bundle cero: El código del servidor no se incluye en el JavaScript del cliente.
  • No pueden usar hooks: No pueden usar useState, useEffect, etc.
  • Composición flexible: Puedes usar Client Components dentro de Server Components.

Para convertir un Server Component a Client Component, simplemente añade 'use client' al inicio del archivo. Sin embargo, hazlo solo cuando sea necesario, ya que esto incluye el componente en el bundle del cliente.

📌 Nota importante: Next.js sigue manteniendo y dando soporte a Pages Router. No será eliminado en el corto plazo, así que si tienes proyectos funcionando con él, puedes estar tranquilo. Sin embargo, todas las nuevas características y optimizaciones se están desarrollando principalmente para App Router.

🛠️ Ejemplo Práctico: Obtención de Datos

Veamos cómo difiere la obtención de datos entre ambos routers con un ejemplo real de una lista de productos:

Con Pages Router:

// pages/products/index.js
import useSWR from 'swr';

function ProductsPage() {
  const { data, error } = useSWR('/api/products', fetcher);

  if (error) return 
Error al cargar productos
; if (!data) return
Cargando...
; return (
    {data.map(product => (
  • {product.name}
  • ))}
); } // pages/api/products.js export default async function handler(req, res) { const products = await db.getProducts(); res.status(200).json(products); }

Con App Router:

// app/products/page.js
async function ProductsPage() {
  // Obtención directa de datos - sin API route necesario
  const products = await db.getProducts();

  return (
    
    {products.map(product => (
  • {product.name}
  • ))}
); } // Si necesitasmutaciones, usa Server Actions: // app/actions.js export async function createProduct(formData) { 'use server'; const name = formData.get('name'); await db.createProduct({ name }); revalidatePath('/products'); }
💡 Tip de rendimiento: En el ejemplo del App Router, no necesitas un endpoint API separado ni una librería como SWR. Los datos se obtienen directamente en el servidor durante el renderizado, lo que reduce la latencia y el código del cliente.

📊 Impacto en el Rendimiento

El App Router puede proporcionar mejoras significativas en varias métricas:

  • Tamaño del bundle JavaScript: Hasta un 30-40% menos de JavaScript enviado al cliente gracias a Server Components.
  • Tiempo de carga inicial: Menos JavaScript significa parseo más rápido y menor TTI (Time to Interactive).
  • Caché más eficiente: El sistema de caché del App Router es más granular y predecible.
  • SEO mejorado: El contenido llega pre-renderizado desde el servidor.
  • Streaming efectivo: Puedes enviar partes de la página según estén listas.
"La elección del router no es solo una decisión técnica, es una declaración de cómo quieres construir y escalar tu aplicación."

🔮 El Futuro de Next.js

Next.js está evolucionando rápidamente y el App Router es el centro de esta evolución. Las próximas características incluyen:

  • Partial Prerendering (PPR): Combina contenido estático y dinámico automáticamente.
  • Mejoras en Server Actions: Más controles y mejor integración con formularios.
  • Cache invalidation más granular: Control preciso sobre qué se cachea y cuándo.
  • Mejoras en streaming: Mejor experiencia de carga progresiva.
📌 Dato interesante: Según las estadísticas de Vercel, las aplicaciones nuevas creadas con Next.js usan App Router en más del 80% de los casos. Esto demuestra que la comunidad ha adoptado rápidamente el nuevo sistema de routing.

📝 Resumen y Recomendación Final

Ambas opciones son válidas y capaces de construir aplicaciones web modernas. Sin embargo, para la mayoría de los casos de uso modernos, el App Router es la elección recomendada porque:

  1. Ofrece mejor rendimiento por defecto con React Server Components.
  2. Proporciona una experiencia de desarrollo más moderna y simplificada.
  3. Recibe todas las nuevas características y optimizaciones.
  4. Reduce la cantidad de código necesario para funcionalidades comunes.
  5. Se alinea mejor con la dirección futura de React.

La única razón válida para usar Pages Router es mantener un proyecto existente donde la migración no justifique el costo-beneficio. Para proyectos nuevos, App Router es el camino a seguir.

🧠 Quiz rápido

Pregunta 1: ¿Cuál es la principal ventaja de los React Server Components en el App Router?

  • a) Permiten usar más hooks de React
  • b) Reducen el tamaño del bundle JavaScript enviado al cliente
  • c) Requieren menos código boilerplate
  • d) Son más fáciles de aprender
✅ Respuesta correcta: b). Los React Server Components se ejecutan únicamente en el servidor, por lo que su código nunca se incluye en el JavaScript enviado al navegador. Esto reduce significativamente el tamaño del bundle y mejora el rendimiento de la aplicación.

Pregunta 2: ¿Puedes usar ambos routers (Pages y App) en el mismo proyecto?

  • a) No, es obligatorio elegir uno desde el inicio
  • b) Sí, pero no simultáneamente
  • c) Sí, Next.js los procesa en paralelo
  • d) Sí, pero App Router tiene prioridad sobre Pages Router
✅ Respuesta correcta: d). Next.js permite tener ambos directorios (/pages y /app) en el mismo proyecto. Cuando coexisten, el App Router tiene prioridad sobre el Pages Router. Esta característica es útil durante migraciones graduales.