Understanding the evolution from Pages Router to App Router in Next.js
getStaticPropsRuns at build time for SSG
getServerSidePropsRuns on each request for SSR
getStaticPathsDefines dynamic routes for SSG
pages/
index.tsx β /
about.tsx β /about
blog/
index.tsx β /blog
[slug].tsx β /blog/[slug]
api/
hello.ts β /api/helloasync componentsDirect async/await in components
fetch with cacheBuilt-in caching strategies
generateStaticParamsDynamic route generation
server actionsDirect mutations & revalidation
app/
page.tsx β /
about/
page.tsx β /about
blog/
page.tsx β /blog
[slug]/
page.tsx β /blog/[slug]
layout.tsx β Shared layout
api/
hello/
route.ts β /api/hello// pages/blog.tsx
export const getStaticProps = async () => {
const posts = await fetch('/api/posts')
return {
props: { posts: await posts.json() },
revalidate: 60
}
}
export default function Blog({ posts }) {
return <div>{/* render posts */}</div>
}// app/blog/page.tsx
async function getPosts() {
const res = await fetch('/api/posts', {
next: { revalidate: 60 }
})
return res.json()
}
export default async function Blog() {
const posts = await getPosts()
return <div>{/* render posts */}</div>
}| Feature | Pages Router | App Router |
|---|---|---|
| Data Fetching | getStaticProps, getServerSideProps | async/await in components |
| Layouts | Custom _app.tsx wrapper | Native layout.tsx files |
| Loading States | Manual implementation | Built-in loading.tsx |
| Error Handling | Custom _error.tsx | Built-in error.tsx |
| Server Components | β Not available | β Default behavior |
| Streaming | β Limited support | β Component-level (Suspense) |
| Data Mutations | API Routes only | β Native Server Actions |