Kuasai rute dinamis di App Router untuk membuat halaman detail artikel. Pelajari cara mengambil data post berdasarkan slug dan merender konten MDX menjadi HTML yang indah.
1320m bacaanKuis WajibMicro Badge Lesson
Bab 3: Menyelami Artikel dengan Rute Dinamis & Render MDX
Kita sudah punya "etalase" yang menampilkan semua artikel kita. Sekarang, saatnya membuka "pintu" agar pengunjung bisa masuk dan membaca setiap artikel secara lengkap. Di bab ini, kita akan membangun halaman detail untuk setiap artikel.
Ini adalah salah satu konsep paling fundamental dan powerful di Next.js: Rute Dinamis. Kita akan membuat satu "template" halaman yang bisa menampilkan konten berbeda-beda, tergantung pada URL yang diakses.
1. Memahami Struktur Rute Dinamis
Di Next.js App Router, untuk membuat rute dinamis, kita menggunakan folder dengan nama yang diapit kurung siku, contohnya [slug].
Di dalam folder src/app/blog/, buat folder baru bernama [slug].
Di dalam folder [slug] tersebut, buat file baru bernama page.tsx.
Struktur foldermu sekarang akan terlihat seperti ini:
bash
src/app/└── blog/ ├── [slug]/ │ └── page.tsx # Template untuk /blog/halo-dunia, /blog/tips-react, dll. └── page.tsx # Halaman daftar semua artikel /blog
Folder [slug] ini adalah sebuah placeholder. Next.js akan secara otomatis menangkap bagian dari URL setelah /blog/ dan memberikannya kepada kita sebagai parameter bernama slug.
2. Mengambil Data untuk Satu Artikel
Sama seperti kita membuat getAllPosts, kita perlu fungsi baru untuk mengambil data dari satu artikel spesifik berdasarkan slug-nya.
Buka kembali file src/lib/post-utils.ts dan tambahkan fungsi baru di bawah getAllPosts:
typescript
// src/lib/post-utils.ts// ... (kode fs, path, matter, dan postsDirectory)// ... (fungsi getAllPosts yang sudah ada)export function getPostBySlug(slug: string) { const fullPath = path.join(postsDirectory, `${slug}.mdx`); const fileContents = fs.readFileSync(fullPath, "utf8"); // Menggunakan gray-matter untuk memisahkan frontmatter dan konten const { data, content } = matter(fileContents); return { slug, frontmatter: data as { title: string; date: string; description: string }, content, };}
Fungsi ini sangat lugas: ia mengambil slug, mencari file .mdx yang cocok, dan mengembalikan frontmatter beserta content (isi artikelnya).
3. Merender Konten MDX Menjadi HTML
Browser tidak mengerti sintaks MDX. Kita butuh sebuah "penerjemah" untuk mengubah string konten MDX kita menjadi komponen React atau HTML yang aman. Di sinilah next-mdx-remote berperan.
A. Instalasi next-mdx-remote
Hentikan server (Ctrl+C) dan jalankan:
bash
npm install next-mdx-remote
B. Membangun Halaman Detail Artikel
Sekarang, mari kita isi file src/app/blog/[slug]/page.tsx yang sudah kita buat tadi.
tsx
// src/app/blog/[slug]/page.tsximport { getPostBySlug } from "@/lib/post-utils";import { MDXRemote } from "next-mdx-remote/rsc";// Props yang diterima halaman ini adalah `params`, yang berisi `slug`type BlogPostPageProps = { params: { slug: string; };};export default function BlogPostPage({ params }: BlogPostPageProps) { const { slug } = params; const { frontmatter, content } = getPostBySlug(slug); return ( <article className="prose dark:prose-invert max-w-none"> <h1 className="text-3xl font-bold mb-2">{frontmatter.title}</h1> <p className="text-sm text-zinc-600 dark:text-zinc-400 mb-8"> Dipublikasikan pada{" "} {new Date(frontmatter.date).toLocaleDateString("id-ID", { year: "numeric", month: "long", day: "numeric", })} </p> {/* Di sinilah keajaiban terjadi! */} <MDXRemote source={content} /> </article> );}
Mari kita bedah kodenya:
BlogPostPageProps: Kita mendefinisikan tipe untuk props. Next.js secara otomatis akan memberikan objek params yang berisi segmen dinamis dari URL. Dalam kasus ini, params.slug.
getPostBySlug(slug): Kita memanggil fungsi helper kita untuk mendapatkan detail artikel.
<MDXRemote source={content} />: Ini adalah komponen dari next-mdx-remote. Kita cukup memberikan content (string MDX) kita ke prop source, dan ia akan melakukan sisanya: mem-parsing dan me-render kontennya menjadi HTML yang aman.
className="prose": Ini adalah utility class ajaib dari plugin Tailwind CSS Typography. Kita akan membahasnya lebih dalam di bab selanjutnya, tapi untuk sekarang, ketahuilah bahwa class ini secara otomatis memberikan styling yang indah pada elemen-elemen HTML seperti judul, paragraf, daftar, dan blok kode.
Jalankan kembali npm run dev, navigasi ke /blog, dan klik salah satu artikel. Tadaa! Kamu sekarang akan dibawa ke halaman detail artikel, lengkap dengan judul, tanggal, dan isi konten yang ter-render dengan cantik.
4. (Opsional tapi Penting) Optimasi Build dengan generateStaticParams
Saat ini, Next.js akan men-generate halaman artikel secara dinamis saat pertama kali diakses. Untuk performa terbaik dan SEO, kita bisa memberitahu Next.js untuk men-generate semua halaman artikel ini saat proses build menjadi file-file HTML statis.
Caranya adalah dengan mengekspor fungsi generateStaticParams di page.tsx kita.
Tambahkan kode berikut di file src/app/blog/[slug]/page.tsx:
tsx
// src/app/blog/[slug]/page.tsximport { getAllPosts, getPostBySlug } from "@/lib/post-utils"; // Tambahkan getAllPostsimport { MDXRemote } from "next-mdx-remote/rsc";// ... (tipe BlogPostPageProps)// Fungsi ini memberitahu Next.js slug apa saja yang adaexport async function generateStaticParams() { const posts = getAllPosts(); return posts.map((post) => ({ slug: post.slug, }));}export default function BlogPostPage({ params }: BlogPostPageProps) { // ... (kode komponen yang sudah ada)}
Dengan fungsi ini, saat kamu menjalankan npm run build, Next.js akan:
Memanggil generateStaticParams.
Mendapatkan daftar semua slug (misal: ['halo-dunia', 'tips-react']).
Menjalankan komponen BlogPostPage untuk setiap slug tersebut.
Menghasilkan file halo-dunia.html dan tips-react.html yang sudah jadi dan siap disajikan secepat kilat dari CDN.
Rangkuman & Langkah Selanjutnya
Hebat! Di bab yang padat ini, kita telah:
✅ Menguasai konsep rute dinamis dengan membuat folder [slug].
✅ Membuat fungsi helper untuk mengambil data satu artikel.
✅ Menggunakan next-mdx-remote untuk me-render konten MDX dengan aman.
✅ Mengoptimalkan performa dengan generateStaticParams.
Blog kita sudah berfungsi penuh! Pengguna bisa melihat daftar artikel dan membacanya. Namun, tampilannya, terutama untuk blok kode, masih bisa kita tingkatkan secara dramatis.
Di bab selanjutnya, kita akan fokus pada sentuhan akhir profesional: membuat konten artikel terlihat sangat indah dengan Tailwind Typography dan syntax highlighting yang canggih.
Checkpoint KuisTarget: 70%
Kuis Rute Dinamis & Render MDX
Kuis ini wajib untuk sertifikat. Kamu tetap bisa lanjut ke pelajaran berikutnya dan mengerjakannya nanti.