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.
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
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 !
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