Next.js App Router: Panduan Lengkap untuk Developer
Next.js 13 memperkenalkan App Router sebagai pendekatan baru untuk routing dan rendering yang lebih powerful dibanding Pages Router.
Artikel ini akan membahas konsep utama dan implementasi praktis.
Apa itu App Router?
App Router adalah sistem routing baru yang dibangun di atas React Server Components dan Suspense.
Beberapa keunggulan utama:
- Server Components by default — komponen dirender di server
- Streaming — UI dapat di-stream secara incremental
- Nested routing — struktur folder yang lebih fleksibel
- Loading states — built-in loading UI dan error handling
Struktur Folder App Router
Di bawah ini contoh struktur folder standar untuk App Router. Gunakan ini sebagai referensi saat membuat route dan nested layouts.
File Structure
Server vs Client Components
Server Components (Default)
Contoh implementasi sederhana di Server Component (render di server):
1// app/posts/page.tsx
2export default async function PostsPage() {
3 const posts = await fetch('https://api.example.com/posts');
4
5 return (
6 <div>
7 {posts.map((post) => (
8 <article key={post.id}>
9 <h2>{post.title}</h2>
10 <p>{post.excerpt}</p>
11 </article>
12 ))}
13 </div>
14 );
15}
16Catatan: gunakan Server Components ketika melakukan data fetching yang tidak butuh interaktivitas di client.
Client Components
Contoh component yang berjalan di client (interaktif):
1"use client";
2
3import { useState } from "react";
4
5export default function SearchForm() {
6 const [query, setQuery] = useState("");
7
8 return (
9 <input
10 value={query}
11 onChange={(e) => setQuery(e.target.value)}
12 placeholder="Search posts..."
13 className="px-3 py-2 border rounded"
14 />
15 );
16}
17Data Fetching Patterns
Fetch di Server Component
Contoh pattern fetch yang memanfaatkan caching bawaan Next.js:
1// Automatic caching dan deduplication
2async function getPosts() {
3 const res = await fetch("https://api.example.com/posts", {
4 next: { revalidate: 3600 }, // Cache 1 jam
5 });
6 return res.json();
7}
8Parallel Data Fetching
Gunakan Promise.all untuk menjalankan beberapa fetch secara bersamaan dan mempercepat waktu tunggu:
1export default async function Dashboard() {
2 // Fetch parallel untuk performa lebih baik
3 const [user, posts, analytics] = await Promise.all([
4 getUser(),
5 getPosts(),
6 getAnalytics(),
7 ]);
8
9 return (
10 <div>
11 <UserProfile user={user} />
12 <PostsList posts={posts} />
13 <Analytics data={analytics} />
14 </div>
15 );
16}
17Loading dan Error Handling
Loading UI
Contoh loading state sederhana untuk tampilan saat data dimuat:
1// app/dashboard/loading.tsx
2export default function Loading() {
3 return (
4 <div className="animate-pulse">
5 <div className="h-8 bg-gray-200 rounded mb-4"></div>
6 <div className="h-4 bg-gray-200 rounded mb-2"></div>
7 <div className="h-4 bg-gray-200 rounded w-3/4"></div>
8 </div>
9 );
10}
11Error Boundary
Contoh Error Boundary untuk menangani error di client:
1// app/dashboard/error.tsx
2"use client";
3
4export default function Error({
5 error,
6 reset,
7}: {
8 error: Error;
9 reset: () => void;
10}) {
11 return (
12 <div className="text-center p-8">
13 <h2>Oops! Something went wrong</h2>
14 <button onClick={reset} className="mt-4 px-4 py-2 bg-blue-500 text-white rounded">
15 Try again
16 </button>
17 </div>
18 );
19}
20Route Groups dan Parallel Routes
Route Groups
Contoh penggunaan route groups untuk memisahkan area (mis. marketing vs dashboard):
File Structure
Parallel Routes
Parallel routes memungkinkan Anda menempatkan slot terpisah yang bisa dirender bersamaan dengan route utama:
File Structure
Metadata API
Contoh penggunaan generateMetadata untuk mengisi meta tags per halaman:
1// app/blog/[slug]/page.tsx
2export async function generateMetadata({ params }) {
3 const post = await getPost(params.slug);
4
5 return {
6 title: post.title,
7 description: post.excerpt,
8 openGraph: {
9 title: post.title,
10 description: post.excerpt,
11 images: [post.coverImage],
12 },
13 };
14}
15Tips Optimasi Performa
-
Gunakan Server Components untuk data fetching.
-
Client Components hanya untuk interaktivity.
-
Streaming dengan Suspense untuk UX yang lebih baik.
-
Route-level caching dengan
revalidate. -
Image optimization dengan
next/image.
Kesimpulan
App Router memberikan foundation yang kuat untuk aplikasi Next.js modern dengan:
-
Performa yang lebih baik melalui Server Components.
-
DX yang lebih baik dengan nested layouts.
-
Built-in streaming dan error handling.
-
Flexible routing patterns.
Migrasi dari Pages Router memang butuh effort, tapi benefits jangka panjang sangat worth it untuk aplikasi yang scalable.
Artikel ini adalah bagian dari series tutorial Next.js. Ingin belajar lebih dalam? Check out dokumentasi resmi dan hands-on projects di repo GitHub saya.