Upgrade your Next.js app from Page Routing to App Routing for better performance, faster navigation, and improved flexibility. With features like React Server Components and optimized data fetching, App Routing enhances interactivity while reducing re-renders. Stay ahead with a more scalable, modern approach to web development. 🚀
Each route corresponds to a page and loads a new HTML file from the server (or a static file).
✅ Pros:
❌ Cons:
App routing (also known as Single Page Application (SPA) Routing) uses JavaScript to handle route changes dynamically without reloading the page. Frameworks like React, Angular, Vue, and Next.js use this approach.
✅ Pros:
❌ Cons:
Here are the steps you can follow to migrate your app from Page Router to App Router.
// pages/[slug].tsx// Page Router - Componentexport const getStaticProps = async ({ params }) => {const id = params.slug;const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);const post = await res.json();return {props: { post },};};export const getStaticPaths = async () => {const res = await fetch("https://jsonplaceholder.typicode.com/posts");const posts = res.json();const paths = posts.map((post) => ({params: { slug: post.id },}));return { paths, fallback: false };};export default function Page(props) {return (<div><h2>{props.post.title}</h2><p>{props.post.body}</p></div>);}
In the App Router of Next.js, routing is managed through a directory-based system. Instead of creating individual files like [filename].tsx for dynamic routes, you define a folder corresponding to the route and place a page.tsx file inside it to serve as the actual page.
| Page Router | App Router | Route |
/pages/post/[slug].tsx | /app/post/[slug]/page.tsx | /post/123, /post/abc, post/* |
In the App Router, pages are now inside the /app directory instead of /pages. Create a new folder for dynamic routes:
/app/post/[slug]/page.tsx
By default, components in the App Router are Server Components, meaning you can directly fetch data without getStaticProps or getServerSideProps. Update your component:
Migrated App Router Component (/app/post/[slug]/page.tsx)
export default async function Page({ params }: { params: { slug: string } }) {const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.slug}`);const post = await res.json();return (<div><h2>{post.title}</h2><p>{post.body}</p></div>);}
✅ No Need for getStaticProps or getStaticPaths – The App Router automatically handles static generation and caching. (dynamicParams can be used as replacement of fallback)
generateStaticParamsIn the Page Router, getStaticPaths was used to predefine dynamic routes. In the App Router, use generateStaticParams:
Add generateStaticParams for Static Pre-rendering
export async function generateStaticParams() {const res = await fetch("https://jsonplaceholder.typicode.com/posts");const posts = await res.json();return posts.map((post: { id: number }) => ({slug: post.id.toString(),}));}
✅ Equivalent to getStaticPaths, ensuring pre-rendering for static pages.
In the App Router, fetching is cached by default. You can configure it with revalidate to enable Incremental Static Regeneration (ISR):
export default async function Page({ params }: { params: { slug: string } }) {const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.slug}`, {next: { revalidate: 60 }, // Revalidate every 60 seconds});const post = await res.json();return (<div><h2>{post.title}</h2><p>{post.body}</p></div>);}
✅ Improves Performance – Pages are cached and revalidated only when needed.
Once all your components are migrated, delete the old /pages directory to fully transition to the App Router.
For a comprehensive guide on migrating from the Pages Router to the App Router in Next.js, please refer to the official Next.js documentation.