Next.js 14 and the App Router represent the biggest change to React application development since hooks. If you’re using Next.js or evaluating it, here’s what actually changed, what the new features mean in practice, and whether to migrate.
The Old Way: Pages Router
The Pages Router maps files in /pages to routes. /pages/about.js renders at /about. Data fetching used getServerSideProps (SSR) or getStaticProps (SSG). This model is still supported and Vercel has committed to long-term Pages Router support.
The Big Change: React Server Components (RSC)
This is the most important concept. In the App Router, components are server components by default — they render on the server and send HTML to the browser, never shipping their JavaScript to the client. This reduces bundle size and improves initial page load significantly.
Client components (interactive, stateful) are now opt-in: add 'use client' at the top of the file. The mental model: “Does this component need interactivity? No → server component, zero client bundle cost. Yes → client component.”
New Data Fetching: No More getServerSideProps
Server components can directly call async functions. Next.js automatically deduplicates requests and handles caching:
async function ProductPage({ params }) {
const product = await fetch(`/api/products/${params.id}`).then(r => r.json())
return <div>{product.name}</div>
}Significantly cleaner than the old data fetching APIs, especially for nested data requirements across deeply nested layouts.
Co-located Layouts and Streaming
Layouts: Persistent across navigation within the same layout group — no re-render when navigating between pages sharing a layout. Eliminates sidebar flicker and enables smooth transitions.
Streaming: Components that haven’t finished data fetching stream in progressively. A loading.tsx file automatically shows loading UI while the page component fetches. Users get immediate visual feedback without complex loading state management.
Server Actions: Forms Without API Routes
Server Actions let you call server functions directly from React components, simplifying form handling:
async function submitForm(formData: FormData) {
'use server'
await db.users.create({ name: formData.get('name') })
redirect('/success')
}Should You Upgrade?
New projects: Yes — start with App Router. Better mental model, better performance, the direction Next.js is heading.
Existing Pages Router projects: Not urgent. Both routers coexist in Next.js 13/14 — migrate incrementally, route by route, when your roadmap allows. The Pages Router isn’t being removed.
Avoid migrating when: In the middle of a major feature, your team isn’t familiar with RSC concepts yet, or your project heavily relies on patterns that work differently in App Router.