Next.js, a popular web development framework, introduced the new App Router as its default routing system in version 13.
I'm sure there are some people who are involved in projects using both Pages Router and App Router and are confused as to which way to write it. That's me!!
In particular, there are significant differences between the Pages Router and the App Router in areas that relate to the core of application development, such as how to define routes based on file structure, how to handle dynamic parts of URLs, how rendering works, and how to retrieve data from APIs.
Focusing on the "frequently confused" points, I'll briefly list the main differences between Pages Router and App Router as a reminder!
Differences in file routing
Pages Router: The simplicity of converting file names into paths
Placed under the pages directory.js
, .jsx
, .ts
, .tsx
It's as simple as the file name becoming the URL path.
example:src/page/about.tsx
⇒ Routing is/about
It will be.
App Router: Organizing by folder and specific filename
App Routersrc/app
You can route by placing folders and files under it.
However, if you add a specific file name called "page" to the file name used for routing, it will be treated as the content of the page corresponding to that path.
example:src/app/about/page.tsx
⇒ Routing is/about
It will be.
Special files that characterize App Router
In addition to page.tsx, there are other meaningful files in App Router.
app/
├── page.tsx --> Page content. This is the file you'll use most often.
├── route.tsx --> API definition (cannot coexist with page.js).
├── layout.tsx --> Common appearance.
├── loading.tsx --> Loading screen.
├── error.tsx --> Error screen.
├── global-error.tsx --> Global error screen.
├── template.tsx --> Common appearance (reset layout).
├── default.tsx --> Default screen.
└── not-found.tsx --> Screen displayed when the notFound function is thrown.
What surprised me personally was not-found.tsx. Just by preparing this page, it will automatically be displayed when you access a non-existent URL. I was impressed by how easy it was to implement.
Rendering differences
Components in the Pages Router are basically designed to be interactive on the client side, and rendering on the server side is mainly done to speed up initial display and for SEO purposes.useState
or useEffect
You can freely use React Hooks such as these in your Page component and its child components.
On the other hand, App Routerapp/
The components inUnless explicitly specified, it will be treated as a server component by default..ThereforeuseState
or useEffect
such asReact hooks are not availableClient-side actions, such as onClickEvent handlers are also not available.
So, to make a CSR using App Router,use client
Write:
use client
Server Component and Client ComponentDeclaring Boundariesis.use client
If you declare it, not only that component but all its imports will be considered as Client Components.
Dynamic Routing [○○]
Next.js provides a mechanism for handling "dynamic URLs" where part of the URL changes depending on the user or content, such as blog or news article detail pages.Dynamic Routingis.
For example, suppose there is a link that takes you to article A and 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>
);
}
Link destinations


If you want dynamic routing,[slug]
If you create a file calledpost/A
butpost/B
But you can use the same template.
*The naming in [ ] is optional.slug
It doesn't have to be
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>
);
}
params
We use.params.slug
to the URL[slug]
The part will be included.
※ params
Previously, parameter acquisition did not need to be asynchronous, but from Next.js 15 onwards, it has been changed to be asynchronous.props
It seems that you need to define it as a Promise type.
For Pages Rouer
/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>
);
}
useRouter
We use.router.query.slug
to the URL[slug]
The value of the part will be entered.
How to get API data
microCMS, which is featured prominently in this Liberogic column, works well with frameworks like Next.js.
App Router
Keep it simplefetch
oraysnc
await
You can use
however,use client
The file that declares this will become a CSR.aysnc
await
will no longer be usable!
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();
}
Callee
export default function Example() {
const data = await getPost()
// ... data を使って表示 ...
}
For Pages Router
getStaticProps
The data obtained usingprops
to the page component.
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,
},
};
}
Callee
export default function Example({ data }) {
// ... data を使って表示 ...
}
Understand the two routers and master Next.js!
In my case, the first project I used Next.js for was App Router.
Later, when I was working on another project and using Pages Router, I found myself wondering, "When creating a new page, should the file name be index.tsx or page.tsx?"
This article only covers a small part of Next.js, but by looking into the differences between App Router and Pages Router, I was able to clarify things in my own mind.
Personally, I like how easy it is to write App Router, but I would like to be able to handle Pages Router projects as well.
The ideal situation would be to gain a deeper understanding of Next.js and be able to use different routers depending on the project or work!
I develop front-end projects using JavaScript, React, and Next.js, focusing on markup. I feel happy when a site I've worked on is successfully published! My hobby is playing the guitar. I enjoy both writing and playing code!
Hiratchi
Front-end engineer / Joined in 2022