Sejak Next.js 13, ada dua cara untuk mengatur routing di aplikasi kamu: App Router dan Pages Router. Kalau baru mulai belajar Next.js, perbedaan keduanya bisa bikin bingung. Artikel ini menjelaskan apa bedanya dan mana yang sebaiknya kamu pilih.
Pages Router adalah sistem routing lama yang sudah ada sejak awal Next.js. Cara kerjanya sederhana: setiap file di folder pages/ otomatis menjadi sebuah route.
pages/
├── index.tsx → /
├── about.tsx → /about
└── blog/
├── index.tsx → /blog
└── [slug].tsx → /blog/:slug
Sistem ini sudah terbukti stabil dan dipakai di jutaan proyek. Dokumentasinya lengkap, tutorial-nya banyak, dan mayoritas library pihak ketiga sudah mendukungnya.
App Router diperkenalkan di Next.js 13 dan menjadi default sejak Next.js 14. Routing-nya menggunakan folder app/ dengan konvensi file khusus.
app/
├── page.tsx → /
├── about/
│ └── page.tsx → /about
└── blog/
├── page.tsx → /blog
└── [slug]/
└── page.tsx → /blog/:slug
App Router dibangun di atas React Server Components, membuka fitur-fitur baru yang tidak tersedia di Pages Router.
| App Router | Pages Router | |
|---|---|---|
| Folder utama | app/ |
pages/ |
| Default sejak | Next.js 14 | Next.js awal |
| Server Components | ✅ Ya (default) | ❌ Tidak |
| Layouts nested | ✅ Mudah | ⚠️ Perlu workaround |
| Data fetching | async/await langsung |
getServerSideProps / getStaticProps |
| Loading & error UI | ✅ loading.tsx / error.tsx |
⚠️ Manual |
| Streaming | ✅ Ya | ❌ Tidak |
| Stabilitas | Masih berkembang | ✅ Sangat stabil |
| Ekosistem library | Masih menyesuaikan | ✅ Sudah mature |
Ini adalah perbedaan yang paling sering dirasakan saat berpindah dari Pages Router ke App Router.
// pages/blog/[slug].tsx
export async function getServerSideProps({ params }) {
const post = await getPost(params.slug)
return {
props: { post }
}
}
export default function BlogPost({ post }) {
return <article>{post.content}</article>
}
Data fetching dipisahkan dari komponen menggunakan fungsi khusus seperti getServerSideProps atau getStaticProps.
// app/blog/[slug]/page.tsx
async function BlogPost({ params }) {
const post = await getPost(params.slug) // Langsung di dalam komponen
return <article>{post.content}</article>
}
export default BlogPost
Lebih bersih — fetch data langsung di dalam komponen tanpa fungsi terpisah.
Salah satu fitur terkuat App Router adalah nested layouts — layout yang bisa berbeda-beda di setiap segmen URL, tanpa re-render ulang saat navigasi.
app/
├── layout.tsx ← Layout global (navbar, footer)
├── dashboard/
│ ├── layout.tsx ← Layout khusus dashboard (sidebar)
│ ├── page.tsx → /dashboard
│ └── settings/
│ └── page.tsx → /dashboard/settings
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }) {
return (
<div className="dashboard">
<Sidebar />
<main>{children}</main>
</div>
)
}
Di Pages Router, hal yang sama membutuhkan workaround manual yang lebih rumit.
App Router menyediakan konvensi file bawaan untuk loading dan error state:
app/
├── blog/
│ ├── page.tsx
│ ├── loading.tsx ← Otomatis tampil saat data loading
│ └── error.tsx ← Otomatis tangkap error di route ini
// app/blog/loading.tsx
export default function Loading() {
return <div>Memuat artikel...</div>
}
Di Pages Router, kamu harus mengelola state loading dan error secara manual di setiap halaman.
Meskipun App Router adalah arah masa depan Next.js, ada kondisi di mana Pages Router masih masuk akal:
Bisa. Next.js mendukung penggunaan App Router dan Pages Router dalam satu proyek secara bersamaan. Ini berguna saat migrasi bertahap dari Pages Router ke App Router.
my-app/
├── app/ ← App Router (halaman baru)
│ └── dashboard/
│ └── page.tsx
└── pages/ ← Pages Router (halaman lama)
└── about.tsx
Kalau kamu memulai proyek baru hari ini, pilih App Router. Ini adalah standar Next.js ke depannya dan menawarkan Developer Experience yang lebih baik dengan fitur yang lebih lengkap.
Kalau kamu punya proyek Pages Router yang sudah berjalan, tidak perlu buru-buru migrasi. Pages Router masih didukung penuh dan tidak akan dihapus dalam waktu dekat. Migrasi bisa dilakukan bertahap saat kamu dan tim sudah siap.
Ingin tahu lebih dalam tentang konsep di balik App Router? Baca artikel kami tentang Server Components vs Client Components — fondasi utama yang membuat App Router berbeda dari Pages Router.
Tidak dalam waktu dekat. Vercel dan tim Next.js sudah menegaskan bahwa Pages Router tetap didukung. Namun, semua fitur baru Next.js hanya akan hadir di App Router, sehingga Pages Router tidak akan berkembang lebih jauh.
Tidak — justru sebaliknya. App Router lebih cepat karena menggunakan Server Components yang mengurangi JavaScript yang dikirim ke browser. Namun, kurva belajarnya lebih tinggi dan beberapa konfigurasi awal butuh penyesuaian.
Bisa. Next.js mendukung keduanya berjalan bersamaan dalam satu proyek. Kamu bisa migrasi halaman per halaman tanpa harus mengubah seluruh proyek sekaligus.
Belum tentu. Beberapa library yang bergantung pada Context API atau hooks tertentu mungkin belum kompatibel dengan Server Components. Pastikan cek dokumentasi library yang kamu gunakan sebelum migrasi.
Pages Router lebih mudah dipelajari karena konsepnya lebih sederhana dan tutorialnya jauh lebih banyak. App Router membutuhkan pemahaman tambahan tentang Server Components dan Client Components. Jika baru mulai belajar Next.js, tidak ada salahnya mulai dengan App Router karena itulah standar saat ini.
Tidak. Kedua fungsi tersebut hanya tersedia di Pages Router. Di App Router, data fetching dilakukan langsung di dalam komponen menggunakan async/await tanpa fungsi khusus.