Featured image of post Conceptos básicos del App Router de Next.js y consejos de migraciónFeatured image of post Conceptos básicos del App Router de Next.js y consejos de migración

Conceptos básicos del App Router de Next.js y consejos de migración

Una guía sobre los fundamentos del App Router de Next.js, que cubre conceptos de diseño de enrutamiento para desarrolladores que planean migrar.

Introducido en Next.js 13, el App Router adopta un enfoque fundamentalmente diferente al enrutamiento y renderizado en comparación con el Pages Router tradicional. Ahora estable y ampliamente adoptado, analicemos los conceptos básicos para aquellos que planean migrar.

App Router vs Pages Router

CaracterísticaPages RouterApp Router
EnrutamientoBajo pages/Bajo app/
ComponentesClient Component por defectoServer Component por defecto
LayoutsImplementación manuallayout.js anidable
CargaImplementación manualAutomática mediante loading.js
Obtención de datosgetServerSideProps, etc.async directo dentro de componentes

1. Enrutamiento basado en archivos

La estructura de carpetas dentro de app/ se asigna directamente a las rutas URL.

app/
├── page.js          → /
├── layout.js        → Layout compartido para todas las páginas
├── about/
│   └── page.js      → /about
└── blog/
    ├── page.js      → /blog
    └── [slug]/
        └── page.js  → /blog/hello-world (ruta dinámica)
// app/blog/[slug]/page.js
export default async function BlogPost({ params }) {
  const { slug } = await params;
  const post = await getPost(slug);
  return <article>{post.title}</article>;
}

2. Sistema de layouts

layout.js se aplica automáticamente a todas las páginas bajo su carpeta. Los layouts se pueden anidar.

// app/layout.js (layout raíz)
export default function RootLayout({ children }) {
  return (
    <html lang="es">
      <body>
        <header>Encabezado del sitio</header>
        {children}
        <footer>Pie del sitio</footer>
      </body>
    </html>
  );
}
// app/blog/layout.js (layout de la sección blog)
export default function BlogLayout({ children }) {
  return (
    <div className="blog-wrapper">
      <aside>Barra lateral</aside>
      <main>{children}</main>
    </div>
  );
}

3. Estados de carga y error

Coloca loading.js y error.js en una carpeta para obtener automáticamente interfaces de carga y error.

// app/blog/loading.js
export default function Loading() {
  return <div>Cargando...</div>;
}
// app/blog/error.js
'use client';
export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Algo salió mal</h2>
      <button onClick={reset}>Intentar de nuevo</button>
    </div>
  );
}

4. Server Components vs Client Components

En App Router, los Server Components son el valor predeterminado — este es el cambio clave.

Server ComponentClient Component
Renderiza enServidorNavegador
useState / useEffect❌ No disponible✅ Disponible
Acceso directo a BD✅ Posible❌ No posible
Tamaño del bundlePequeño (sin JS enviado)Grande
Interacciones❌ No posible✅ Posible
// Server Component (por defecto) — puede acceder a BD directamente
export default async function PostList() {
  const posts = await db.query('SELECT * FROM posts');
  return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}

Regla general: escribe Server Components por defecto, y usa Client Components solo para las partes interactivas más pequeñas.

5. Patrones de obtención de datos

App Router te permite llamar a fetch() directamente dentro de los componentes. El almacenamiento en caché está activado por defecto.

// En caché (predeterminado)
const data = await fetch('https://api.example.com/posts');

// Sin caché (nuevo en cada solicitud)
const data = await fetch('https://api.example.com/posts', {
  cache: 'no-store',
});

// Revalidación basada en tiempo
const data = await fetch('https://api.example.com/posts', {
  next: { revalidate: 60 },
});

6. Grupos de rutas

Envuelve un nombre de carpeta en ( ) para organizar archivos sin afectar la URL.

app/
├── (marketing)/
│   ├── page.js      → /
│   └── pricing/
│       └── page.js  → /pricing
└── (shop)/
    ├── layout.js    → Layout específico de la tienda
    └── products/
        └── page.js  → /products

Ideal para usar diferentes layouts entre secciones sin prefijos de URL.

Resumen

App Router es una nueva arquitectura centrada en Server Components, y su filosofía difiere significativamente de Pages Router. Puede ser confuso al principio, pero ceñirse a “Server Components primero, Client Components solo donde sea necesario” conducirá a aplicaciones de alto rendimiento. Para migraciones, comienza con páginas más pequeñas y avanza gradualmente.