Switching the display language

Topics

Next.js Pages Router and App Router: Clarifying the often confusing differences

  • column

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, .tsxIt's as simple as the file name becoming the URL path.

example:src/page/about.tsx⇒ Routing is/aboutIt will be.

App Router: Organizing by folder and specific filename

App Routersrc/appYou 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/aboutIt 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 useEffectYou 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 clientWrite:

use client

Server Component and Client ComponentDeclaring Boundariesis.use clientIf 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.

For example, a capture of a page with links 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

Capturing post/A page
Capture of post/B page

If you want dynamic routing,[slug]If you create a file calledpost/Abutpost/BBut you can use the same template.
*The naming in [ ] is optional.slugIt 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>
  );
}

paramsWe use.params.slugto the URL[slug]The part will be included.

paramsPreviously, parameter acquisition did not need to be asynchronous, but from Next.js 15 onwards, it has been changed to be asynchronous.propsIt 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>
  );
}

useRouterWe use.router.query.slugto 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 simplefetchoraysnc awaitYou can use

however,use clientThe file that declares this will become a CSR.aysnc awaitwill 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

getStaticPropsThe data obtained usingpropsto 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!

Written by

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

We pride ourselves on our reliable team structure and speedy response capabilities.

At Liberogic, our experienced staff proactively drive projects forward, which is why we are highly regarded by our clients.
We ensure that project managers and directors are properly assigned to ensure the smooth progress of the entire project. We prevent unnecessary cost increases from full commitments and allocate resources to the right people in the right places, and are well-known for the speed with which we can grasp the work content, create and submit estimates.

Please note that we do not actively provide on-site services such as SES.

We support almost all major project management and chat tools, including Slack, Teams, Redmine, Backlog, Asana, Jira, Notion, Google Workspace, Zoom, and Webex.

In large-scale projects using SES and offshoreDo you have any technical issues or concerns about how to tackle them?

Case Study