Topics

Pages Router et App Router de Next.js : clarifier des différences souvent confondues

  • column

Next.js, très apprécié comme framework de développement web, a introduit dans sa version 13 le App Router comme système de routage par défaut.

En travaillant sur des projets utilisant à la fois Pages Router et App Router, il arrive de se demander « laquelle des deux syntaxes était-ce déjà ? » et de les confondre. C'est exactement mon cas !

En particulier, du mode de définition du routage basé sur la structure des fichiers à la gestion des parties dynamiques des URL, en passant par le fonctionnement du rendu et la récupération de données depuis une API, Pages Router et App Router présentent des différences importantes touchant aux fondements du développement d'applications.

En nous concentrant sur les points les plus souvent confondus, nous présentons ici, de manière simple bien que non exhaustive, les principales différences entre Pages Router et App Router, sous forme d'aide-mémoire !

Différences de routage des fichiers

Pages Router : la simplicité d'un nom de fichier qui devient directement le chemin

La simplicité réside dans le fait que le nom des fichiers .js, .jsx, .ts et .tsx placés dans le répertoire pages devient directement le chemin de l'URL.

Exemple : src/page/about.tsx ⇒ le routage correspond à /about.

App Router : une structure basée sur les dossiers et des noms de fichiers spécifiques

Le App Router permet de définir les routes en plaçant des dossiers et des fichiers dans le répertoire src/app.

Cependant, un fichier nommé spécifiquement page utilisé pour le routage est traité comme le contenu de la page correspondant à ce chemin.

Exemple : src/app/about/page.tsx ⇒ la route devient /about.

Les « fichiers spéciaux » qui caractérisent le App Router

Par ailleurs, le App Router comprend d'autres fichiers dotés d'une signification particulière, en plus 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関数がスローされたときの画面

Ce qui m'a le plus surpris, c'est not-found.tsx. Il suffit de créer cette page pour qu'elle s'affiche automatiquement lorsqu'une URL inexistante est consultée. J'ai été impressionné de voir que la mise en œuvre pouvait être aussi simple...

Différences de rendu

Dans le Pages Router, les composants sont par principe conçus pour être interactifs côté client, et le rendu côté serveur sert principalement à accélérer l'affichage initial et à améliorer le SEO. Les hooks React tels que useState et useEffect peuvent être utilisés librement dans les composants de page et leurs composants enfants.

En revanche, les composants situés dans app/ du App Router sont traités par défaut comme des composants serveur, sauf indication explicite contraire. Par conséquent, les hooks React tels que useState et useEffect ne peuvent pas être utilisés. Les actions côté client et les gestionnaires d'événements comme onClick ne sont pas non plus disponibles.

Pour passer en CSR dans le App Router, il suffit donc d'ajouter use client.

use client

Il s'agit de la délimitation entre les Server Components et les Client Components. Lorsque use client est déclaré, non seulement ce composant mais aussi tous les modules qu'il importe sont considérés comme des Client Components.

Routage dynamique [○○]

Le routage dynamique de Next.js est le mécanisme qui permet de gérer les « URL dynamiques », dont une partie varie selon l'utilisateur ou le contenu, comme les pages de détail d'articles de blog ou d'actualités.

Prenons l'exemple de liens menant aux articles A et B.

Par exemple, une capture d'une page présentant des liens vers l'article A et l'article 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>
  );
}

Destination de chaque lien

Capture de la page post/A
Capture de la page post/B

Avec le routage dynamique, il suffit de créer un fichier [slug] pour utiliser le même modèle pour post/A comme pour post/B.
※ Le nom entre [ ] est libre ; il n'est donc pas obligatoire d'utiliser slug

Dans le cas de l'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>
  );
}

On utilise params. params.slug contient la partie [slug] de l'URL.

※ La récupération des paramètres via params n'avait pas besoin d'être asynchrone jusqu'ici, mais depuis Next.js 15, elle doit se faire de manière asynchrone. Il semble donc nécessaire de définir props avec le type Promise.

Dans le cas 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>
  );
}

On utilise useRouter. router.query.slug contient la valeur de la partie [slug] de l'URL.

Méthodes de récupération des données API

Comme le montre cette chronique Liberogic, microCMS s'associe très bien à des frameworks comme Next.js.

Dans le cas de l'App Router

Il suffit d'utiliser simplement fetch, async et await.

Cependant, un fichier qui déclare use client devient un rendu côté client (CSR), et async ainsi que await ne peuvent alors plus être utilisés !


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();
}

Appelant

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

Dans le cas de Pages Router

Utilisez getStaticProps et transmettez les données récupérées au composant de page sous forme de 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,
    },
  };
}

Appelant

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

Comprenez les deux routeurs et maîtrisez Next.js !

Dans mon cas, le premier projet sur lequel j'ai utilisé Next.js employait App Router.

Par la suite, sur un autre projet, j'ai travaillé avec le Pages Router et je me suis demandé : « Pour créer une nouvelle page, est-ce index.tsx ou page.tsx le bon nom de fichier ? »

Ce contenu ne couvre qu'une petite partie de Next.js, mais en revoyant les différences entre l'App Router et le Pages Router, j'ai pu clarifier les choses dans mon esprit.

Personnellement, j'apprécie la syntaxe de l'App Router, car elle est plus lisible, mais je voudrais aussi être en mesure de bien travailler sur des projets utilisant le Pages Router.

L'idéal est de bien comprendre Next.js et de savoir choisir le routeur adapté à chaque projet et à chaque réalisation !

Auteur de cet article

Je travaille sur le développement frontend, principalement en balisage, avec JavaScript, React et Next.js. Je suis ravi lorsque les sites auxquels j'ai contribué sont mis en ligne avec succès ! Passionné de guitare, j'aime aussi les chats et les patates douces grillées 🐱🍠

Hiratchi

Ingénieur frontend / Entré en 2022

Voir les articles de cet auteur

Une équipe fiable et une réactivité rapide, qui font notre fierté

Chez Liberogic, nos collaborateurs expérimentés pilotent activement les projets, ce qui vaut à l'entreprise une grande satisfaction de la part de ses clients.
Nous veillons à désigner des chefs de projet et des directeurs de projet qualifiés afin de faire avancer l'ensemble du projet en douceur. Grâce à un modèle d'allocation des ressources au plus juste, évitant une hausse inutile des coûts liée à un engagement à temps plein, nous sommes également reconnus pour la rapidité avec laquelle nous comprenons les besoins et établissons/soumettons les devis.

Remarque : Liberogic ne propose pas de prestations de type SES (mise à disposition de personnel sur site) et vous remercie de bien vouloir en tenir compte.

Nous prenons en charge pratiquement tous les principaux outils de gestion de projet et de messagerie, notamment Slack, Teams, Redmine, Backlog, Asana, Jira, Notion, Google Workspace, Zoom, Webex, etc.

Dans les projets de grande envergure impliquant des SES ou de l'offshore, avez-vous des difficultés techniques ou des questions sur la manière de les aborder ?

Études de cas