Next.js provides two main routing architectures: Pages Router and App Router. They have significant differences in design philosophy, features, and performance.
Pages Router
Pages Router is Next.js's traditional routing system, based on the pages directory.
Features
- Simple File Structure
shellpages/ index.js about.js blog/ [slug].js
- Data Fetching Methods
getStaticProps: Fetch data at build timegetServerSideProps: Fetch data on each requestgetStaticPaths: Define paths for dynamic routes
- Lifecycle
- Supports React's full lifecycle
- Uses
useEffectfor client-side data fetching
- Route Hooks
javascriptimport { useRouter } from 'next/router'; const router = useRouter(); console.log(router.pathname, router.query);
Pros
- Mature and stable, with comprehensive documentation and community support
- Gentle learning curve
- Suitable for small to medium projects
Cons
- Doesn't support nested routes
- Doesn't support server components
- Limited performance optimization
App Router
App Router is the new routing system introduced in Next.js 13+, based on the app directory.
Features
- File Structure
shellapp/ page.js layout.js about/ page.js blog/ [slug]/ page.js
- Server Components and Client Components
javascript// Server component (default) async function BlogList() { const posts = await fetch('https://api.example.com/posts').then(r => r.json()); return <div>{posts.map(post => <Post key={post.id} {...post} />)}</div>; } // Client component 'use client'; import { useState } from 'react'; function InteractiveComponent() { const [count, setCount] = useState(0); return <button onClick={() => setCount(c => c + 1)}>{count}</button>; }
- Data Fetching
javascript// Fetch data directly in the component async function Page() { const data = await fetch('https://api.example.com/data', { next: { revalidate: 60 } // ISR }).then(r => r.json()); return <div>{data.content}</div>; }
- Layout System
javascript// app/layout.js export default function RootLayout({ children }) { return ( <html> <body> <Header /> {children} <Footer /> </body> </html> ); }
- Route Hooks
javascriptimport { useParams, usePathname } from 'next/navigation'; const params = useParams(); const pathname = usePathname();
Pros
- Supports server components, reducing client-side JavaScript
- Supports nested routes and layouts
- Better performance and user experience
- More modern API design
Cons
- Steeper learning curve
- Relatively new, ecosystem still developing
- Need to understand the difference between server and client components
Main Differences Comparison
| Feature | Pages Router | App Router |
|---|---|---|
| Directory | pages/ | app/ |
| Server Components | Not supported | Supported |
| Nested Routes | Not supported | Supported |
| Layout System | Limited | Powerful |
| Data Fetching | getStaticProps/getServerSideProps | Directly in component |
| Route Hooks | next/router | next/navigation |
| File Convention | index.js | page.js |
| Loading States | Manual implementation | Automatic loading.js support |
| Error Handling | Manual implementation | Automatic error.js support |
| Streaming Rendering | Not supported | Supported |
Migration Recommendations
When to Use Pages Router
- Existing projects already using Pages Router
- Small projects that don't need complex features
- Team more familiar with Pages Router
When to Use App Router
- New projects
- Need server components to optimize performance
- Need nested routes and complex layouts
- Need better SEO and performance
Mixed Usage
Next.js allows using both routers simultaneously:
pages/directory uses Pages Routerapp/directory uses App Router
javascript// Both directories can coexist pages/ api/ hello.js // API routes app/ page.js // Main page
Best Practices
- Prioritize App Router for new projects: Get better performance and development experience
- Gradual migration: Existing projects can gradually migrate pages to App Router
- Use server components wisely: Make components that don't need interactivity server components
- Leverage layout system: Use nested layouts to share UI
- Maintain consistency: Try to use one router consistently in a project
Choosing which router to use depends on project requirements, team experience, and performance needs. App Router represents the future direction of Next.js, but Pages Router remains a reliable choice.