Migrating from Next.js Pages Router to App Router is a significant but manageable project. The recommended approach is incremental – both routers can run in parallel in the same Next.js project, so you migrate route by route rather than all at once.
Next.js App Router was introduced in Next.js 13.4 and became stable and recommended in Next.js 14. By 2026, nearly all new Next.js projects use App Router. If you’re on Pages Router, here’s everything you need to know about migrating.
Key differences
Concept Pages Router App Router File convention pages/index.tsx app/page.tsx Layout _app.tsx wraps all pages layout.tsx per segment Data fetching getServerSideProps / getStaticProps async Server Components Client components All client by default Server by default, ‘use client’ to opt in Metadata next/head in each page metadata export API routes pages/api/route.ts app/api/route/route.ts Loading states Manual loading.tsx convention Error boundaries Manual error.tsx convention Streaming Not supported Built-in with SuspenseStep 1: Upgrade Next.js
npm install next@latest react@latest react-dom@latest
Enter fullscreen mode Exit fullscreen mode
Step 2: Create the app directory
Both routers coexist. Create an app directory – Next.js serves routes from app when available, falling back to pages for anything not yet migrated.
/app
layout.tsx # Required root layout
page.tsx # Replaces pages/index.tsx when ready
/pages
index.tsx # Still works until removed
about.tsx # Unmigrated pages keep working
api/
auth.ts # API routes in pages/api still work
Enter fullscreen mode Exit fullscreen mode
Step 3: Create the root layout
// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: { default: "My App", template: "%s | My App" },
description: "My app description",
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: `
(function() {
var s = localStorage.getItem('theme');
var sys = matchMedia('(prefers-color-scheme: dark)').matches;
if (s === 'dark' || (!s && sys)) document.documentElement.classList.add('dark');
})();
`}} />
</head>
<body className="bg-background text-foreground">{children}</body>
</html>
);
}
Enter fullscreen mode Exit fullscreen mode
Step 4: Migrate pages one at a time
// Before: pages/about.tsx
export default function AboutPage() {
return <div>About page</div>;
}
// After: app/about/page.tsx
export const metadata = { title: "About" };
export default function AboutPage() {
return <div>About page</div>;
}
Enter fullscreen mode Exit fullscreen mode
Step 5: Migrate data fetching
// Before: Pages Router
export async function getServerSideProps({ params }) {
const post = await fetchPost(params.id);
return { props: { post } };
}
export default function PostPage({ post }) {
return <div>{post.title}</div>;
}
// After: App Router
export default async function PostPage({ params }: { params: { id: string } }) {
const post = await fetchPost(params.id);
return <div>{post.title}</div>;
}
Enter fullscreen mode Exit fullscreen mode
Common migration issues
-
useState/useEffect in Server Components – add
"use client"directive -
next/router vs next/navigation – App Router uses
useRouterfromnext/navigationwith a different API - getStaticPaths → generateStaticParams – function name and return format changed
-
API routes – move from
pages/api/route.tstoapp/api/route/route.tswith named exports (GET,POST) -
next/head → metadata export – export a
metadataobject frompage.tsxinstead
Frequently asked questions
Should I migrate from Pages Router to App Router in 2026?
For active projects, yes. App Router has better performance through React Server Components and simpler data fetching. For stable projects not being actively developed, the migration cost may not be worth the benefit. New projects should always start with App Router.
Can Pages Router and App Router run together?
Yes. This is the recommended migration strategy. Both routers work simultaneously – routes in app/ take precedence over the same routes in pages/. Migrate one route at a time.
Originally published at thekitbase.app
답글 남기기