Topics

Diferencias entre Pages Router y App Router de Next.js, aclaradas

  • column

Next.js, un framework de desarrollo web muy apreciado, introdujo en la versión 13 el nuevo App Router como sistema de enrutamiento predeterminado.

Al trabajar en proyectos que utilizan tanto Pages Router como App Router, es posible que a más de uno le surja la duda de "¿cuál era la forma de escribir esto?". Yo mismo me encuentro en esa situación!

En particular, desde la forma de definir las rutas según la estructura de archivos, pasando por el manejo de las partes dinámicas de la URL, hasta el renderizado y la obtención de datos desde la API, existen diferencias importantes entre Pages Router y App Router que no pueden ignorarse, afectando a los fundamentos del desarrollo de aplicaciones.

Centrándonos en los puntos que suelen generar confusión, resumo en estas notas las principales diferencias entre Pages Router y App Router, aunque de forma breve!

Diferencias en el enrutamiento de archivos

Pages Router: la sencillez de que el nombre del archivo se convierte directamente en la ruta

La sencillez radica en que el nombre de los archivos .js, .jsx, .ts y .tsx ubicados en el directorio pages se convierte directamente en la ruta de la URL.

Ejemplo: src/page/about.tsx → la ruta resultante es /about.

App Router: estructuración mediante carpetas y nombres de archivo específicos

The App Router enables routing by placing folders and files under src/app.

However, a file named specifically "page" used for routing is treated as the content of the page corresponding to that path.

Example: src/app/about/page.tsx → the route becomes /about.

Los "archivos especiales" que caracterizan al App Router

Además, el App Router tiene otros archivos con significado propio, aparte de page.tsx.

app/
├── page.tsx           --> ページの中身。これが一番よく使うファイル
├── route.tsx          --> APIの定義(page.jsと共存不可)
├── layout.tsx         --> 共通の見た目
├── loading.tsx        --> 読み込み中の画面
├── error.tsx          --> エラー時の画面
├── global-error.tsx   --> グローバルエラー画面
├── templete.tsx       --> 共通の見た目(リセットされるレイアウト)
├── default.tsx        --> デフォルトの画面
└── not-found.tsx      --> notFound関数がスローされたときの画面

Lo que más me sorprendió fue not-found.tsx. Basta con crear esta página para que se muestre automáticamente cuando se accede a una URL inexistente. Me impresionó lo fácil que resulta implementarlo...

Diferencias en el renderizado

Los componentes en el Pages Router están pensados, en principio, para ser interactivos en el lado del cliente, y el renderizado en el servidor se utiliza principalmente para acelerar la visualización inicial y para el SEO. Los hooks de React como useState y useEffect pueden usarse libremente dentro de los componentes de página y de sus componentes hijos.

En cambio, los componentes dentro de app/ en el App Router se tratan por defecto como Server Components, salvo que se indique explícitamente lo contrario. Por ello, useState y useEffect y otros hooks de React no pueden utilizarse. Tampoco se pueden usar acciones del lado del cliente ni manejadores de eventos como onClick.

Por eso, para convertir un componente del App Router en CSR, hay que escribir use client.

use client

Es la declaración del límite entre Server Component y Client Component. Al declarar use client, no solo ese componente se considera un Client Component, sino también todos los módulos que importa.

Enrutamiento dinámico [○○]

El enrutamiento dinámico de Next.js es el mecanismo que permite trabajar con "URLs dinámicas", en las que parte de la URL cambia según el usuario o el contenido, como en las páginas de detalle de artículos de un blog o de noticias.

Por ejemplo, supongamos que hay enlaces que llevan al artículo A y al artículo B.

Por ejemplo, captura de una página con enlaces a los artículos A y B
import Link from "next/link";
const linkStyle=`ext-lg font-bold border-b border-primary px-1`

export default function page() {
  return (
    <div>
      <div className="flex gap-6">
        <Link href="/post/A" className={linkStyle}>記事Aへのリンク</Link>
        <Link href="/post/B" className={linkStyle}>記事Bへのリンク</Link>
      </div>
    </div>
  );
}

Destino de cada enlace

Captura de la página post/A
Captura de la página post/B

Para usar enrutamiento dinámico, basta con crear un archivo [slug] para que tanto post/A como post/B utilicen la misma plantilla.
Nota: el nombre de [ ] es libre, por lo que no es obligatorio que sea slug.

En el caso de App Router

/app/post/[slug]/page.tsx

export default aysinc function PostPage({ params }: { params: Promise<{ slug: string }>) {
  const {slug}= await params;
  return (
    <div>
      <h1>記事: {slug}</h1>
    </div>
  );
}

Se utiliza params. En params.slug se recibe la parte [slug] de la URL.

Nota: Hasta ahora, la obtención de parámetros mediante params no necesitaba ser asíncrona, pero desde Next.js 15 se ha cambiado para realizarse de forma asíncrona. Por ello, parece que es necesario definir props como tipo Promise.

En el caso de Pages Router

/pages/post/[slug].tsx


import { useRouter } from 'next/router';

export default function PostPage() {
  const router = useRouter();
  const { slug } = router.query;

  return (
    <div>
      <h1>記事: {slug}</h1>
    </div>
  );
}

Usamos useRouter. router.query.slug contiene el valor de la parte [slug] de la URL.

Cómo obtener datos de la API

Como se muestra en esta columna de Liberogic, microCMS funciona muy bien con frameworks como Next.js.

En el caso de App Router

Basta con usar fetch o async await de forma sencilla.

Sin embargo, los archivos que declaran use client se renderizan en el cliente (CSR), por lo que no se puede usar async await!


async function getPost() {
  const res = await fetch(`https://.../api/data/`);

  // エラーハンドリング例
  if (!res.ok) {
     throw new Error(`Failed to fetch post: ${res.status}`);
  }

  return res.json();
}

Función llamada

export default function Example() {
   const data = await getPost()
   // ... data を使って表示 ...
}

En el caso de Pages Router

Use getStaticProps y pase los datos obtenidos al componente de página como props.


export async function getServerSideProps(context) {
  // context.req, context.res などにアクセス可能
  const res = await fetch(`https://.../api/data/`, {
     headers: { Cookie: context.req.headers.cookie } // 例: Cookieを渡す
  });
  const data = await res.json();

  return {
    props: {
      data,
    },
  };
}

Función llamada

export default function Example({ data }) {
  // ... data を使って表示 ...
}

¡Comprendamos los dos enrutadores y domine Next.js!

En mi caso, el primer proyecto en el que usé Next.js fue con App Router.

Después, en otro proyecto, trabajé con Pages Router y me surgió la duda: "¿Para crear una nueva página, el archivo era index.tsx o page.tsx?"

Aunque este contenido abarca solo una parte de Next.js, al investigar de nuevo las diferencias entre App Router y Pages Router pude organizar mis ideas al respecto.

Personalmente me gusta la forma de escribir código de App Router por su claridad, pero quiero poder responder con solvencia también en proyectos con Pages Router.

Lo ideal es comprender Next.js en profundidad y saber elegir el router adecuado según el proyecto o la producción de cada caso.

Autor de este artículo

Me dedico principalmente al maquetado y al desarrollo frontend con JavaScript, React y Next.js. Me alegra mucho cuando los sitios en los que participo se publican con éxito. Mi afición es tocar la guitarra. Me gustan los gatos y las batatas asadas 🐱🍠

Hirocchi

Ingeniero/a de frontend / Se unió en 2022

Ver los artículos de este miembro del equipo

Equipo de confianza y una respuesta ágil son nuestras fortalezas

En Liberogic, nuestro personal veterano impulsa los proyectos de forma proactiva, por lo que nuestros clientes nos valoran muy positivamente.
Nos esforzamos por asignar de manera adecuada a un gestor de proyectos y a un director, para que el proyecto avance sin contratiempos en su conjunto. Nuestro estilo consiste en distribuir los recursos de forma adecuada a cada tarea, evitando el aumento de costes por dedicaciones completas innecesarias. También somos reconocidos por la rapidez con la que comprendemos el alcance del trabajo y preparamos y presentamos los presupuestos.

Nota: Ten en cuenta que Liberogic no se dedica activamente a los servicios de desarrollo en las instalaciones del cliente (tipo SES).

Puede utilizar prácticamente todas las principales herramientas de gestión de proyectos y de chat, como Slack, Teams, Redmine, Backlog, Asana, Jira, Notion, Google Workspace, Zoom, Webex y más.

En proyectos de gran escala que utilizan SES o externalización offshore, ¿tiene dudas sobre los desafíos técnicos o el enfoque de trabajo?

Casos de Estudio