Lihat semua artikel

Jebakan di Dunia Next.js: 3 Dosa Pemicu Bug yang Kami Pelajari (Dengan Susah Payah)

1 Agustus 2025

Iwan Efendi

Sebuah ilustrasi abstrak representasi kode yang kompleks dan proses debugging

Setiap pengembang memiliki kuburan ide-ide yang dulunya cemerlang. Sebuah repositori pribadi berisi kode yang, pada masanya, terasa seperti terobosan jenius, namun kini menjadi monumen pelajaran berharga. Proyek IR Web ini memiliki kuburan semacam itu. Perjalanan kami membangunnya kembali adalah sebuah studi kasus tentang bagaimana niat baik dapat memicu bug yang paling sulit dilacak di Next.js.

Ini bukanlah artikel teoritis. Ini adalah pengakuan dari medan perang, sebuah peta yang menandai tiga "dosa" utama yang kami lakukan—jebakan yang mungkin juga sedang Anda hadapi.

Dosa #1: Mengaburkan Batas Antara Konten Draf dan Terbit

Ini adalah dosa asal kami, akar dari segala masalah.

Ide yang Tampak Cemerlang: "Bagaimana jika kita bisa melihat pratinjau draf artikel di situs produksi hanya dengan menambahkan ?preview=true di URL? Satu sistem, dua fungsi. Efisien!"

Kenyataannya: Kami menciptakan monster. Dengan mencampurkan logika untuk konten yang diterbitkan dan konten draf di dalam komponen dan fungsi pengambilan data yang sama, kami mengundang kekacauan.

Gejala yang Muncul:

  1. Error Hidrasi Misterius: Error Text content does not match server-rendered HTML menjadi tamu rutin. Server merender halaman untuk pengguna publik, tetapi klien mencoba merender ulang dengan logika pratinjau (atau sebaliknya). Ketidakcocokan ini adalah racun bagi Next.js.
  2. Build yang Rapuh: next build menjadi lotre. Terkadang berhasil, terkadang gagal dengan pesan error yang tidak jelas. Ini karena proses build mencoba mengikuti tautan ke halaman draf yang seharusnya tidak ada.
  3. Kompleksitas Kode yang Meledak: Komponen kami dipenuhi dengan if (isPreview) { ... } else { ... }. Logika yang seharusnya sederhana menjadi bercabang dan sulit dipelihara.

Penebusan Dosa (Solusinya): Kami membuat keputusan yang menyakitkan namun membebaskan: Pemisahan Total.

  • Logika Data yang Tegas: Fungsi getArticles() sekarang secara ketat hanya mengambil artikel dengan published: true di frontmatter. Tidak ada pengecualian.
  • Pratinjau di Lingkungan Terpisah: Jika pratinjau draf diperlukan, itu harus dilakukan di lingkungan pengembangan lokal (localhost) atau di deployment khusus untuk pratinjau, yang sepenuhnya terisolasi dari build produksi.

Pelajaran: Jangan pernah mencampurkan logika konten terbit dan draf dalam satu alur kerja produksi. Perlakukan mereka sebagai dua dunia yang terpisah.

Dosa #2: Mengabaikan "Single Source of Truth" untuk Data

Pada awalnya, logika untuk membaca file .md tersebar di beberapa tempat. Satu fungsi untuk halaman utama, satu lagi untuk halaman tag, dan sedikit modifikasi di halaman artikel.

Gejala yang Muncul:

  • Inkonsistensi: Halaman utama mungkin menampilkan artikel, tetapi halaman tag tidak, karena logika pemfilteran atau pengurutannya sedikit berbeda.
  • Perbaikan Berulang: Memperbaiki bug di satu tempat berarti harus mengingat untuk memperbaikinya di tiga tempat lain. Ini resep untuk kesalahan manusia.

Penebusan Dosa (Solusinya): Kami menciptakan src/lib/data.tsx, sebuah "benteng" yang menjadi satu-satunya sumber kebenaran.

  • Satu Fungsi untuk Mengambil Semua: getArticles() menjadi fungsi inti.
  • Fungsi Lain Membangun di Atasnya: Fungsi seperti getRelatedArticles() atau getArticlesByTag() tidak lagi membaca file sendiri; mereka mengambil data dari getArticles() yang sudah stabil dan kemudian memfilternya.

Pelajaran: Sentralisasikan logika pengambilan data inti Anda. Buat satu fungsi yang andal, lalu biarkan fungsi-fungsi lain menggunakan hasilnya.

Dosa #3: Terlalu Bergantung pada Efek Samping di Klien (useEffect)

Untuk menangani tanggal atau konten dinamis lainnya, kami sering menggunakan useEffect untuk memperbarui tampilan setelah komponen dimuat di klien.

Gejala yang Muncul:

  • Layout Shift (Pergeseran Tata Letak): Pengguna melihat placeholder (misalnya, tanggal "...") lalu tiba-tiba teks berubah setelah beberapa milidetik. Ini mengganggu dan terlihat tidak profesional.
  • Potensi Error Hidrasi: Jika tidak ditangani dengan sangat hati-hati, logika di dalam useEffect masih bisa menyebabkan ketidakcocokan antara render server dan klien.

Penebusan Dosa (Solusinya): Kami mengadopsi pendekatan "utamakan render server" dan hanya menggunakan hidrasi klien jika benar-benar diperlukan.

  • Komponen Server Secara Default: Sebanyak mungkin komponen tetap menjadi React Server Components (RSC) yang hanya berjalan di server.
  • ArticleDate yang Aman: Komponen tanggal kami sekarang dirender dengan format sederhana yang konsisten di server, dan hanya "dipercantik" dengan format lokal di klien setelah hidrasi yang aman, mencegah pergeseran tata letak.

Pelajaran: Lakukan sebanyak mungkin pekerjaan di server. Gunakan komponen klien dan useEffect hanya untuk interaktivitas yang memang harus terjadi di browser.

Kesimpulan

Perjalanan membangun kembali IR Web mengajarkan kami bahwa kode terbaik bukanlah yang paling "cerdas" atau "efisien" secara teori, tetapi yang paling stabil, dapat diprediksi, dan mudah dipelihara. Dengan memisahkan urusan, menyentralisasikan logika, dan menghormati batasan antara server dan klien, kami akhirnya membangun fondasi yang tidak hanya bebas dari bug-bug lama, tetapi juga siap untuk berkembang di masa depan.


Bacaan Terkait

IE

Ditulis Oleh

Iwan Efendi

Pengembang web yang bersemangat dalam membangun produk digital dan berbagi pengetahuan melalui tulisan.

Komentar dan Diskusi

Memuat komentar...