Hydration Mismatch di Next.js untuk Website Bisnis Indonesia: Cara Bug Senyap Ini Bikin CLS Memburuk dan Konversi Hilang di 2026
TL;DR: Hydration mismatch terjadi ketika HTML yang di-render server berbeda dengan yang di-render React di klien. Per April 2026, bug ini umum di Next.js App Router dan jadi penyebab tersembunyi [CLS](/glosarium/cls-cumulative-layout-shift) memburuk. Marketer jarang melaporkannya karena tidak terlihat di GA4, tapi dampaknya nyata di rasio konversi halaman landing.
Dalam beberapa proyek terakhir, saya melihat skenario yang sama berulang. Tim developer melaporkan website "lancar" di local dan staging. Tapi ketika [CrUX](/glosarium/crux) dashboard menampilkan data field, CLS di atas 0,1 dan posisi konten di halaman landing tiba-tiba "loncat" beberapa milidetik setelah load. Penyelidikan biasanya berujung di satu penyebab: hydration mismatch.
Bug ini senyap. React 18 dan 19 hanya menampilkan warning di console developer, tidak crash, tidak alert ke user. Tapi efek visualnya nyata, dan untuk halaman yang punya CTA di atas fold, satu shift kecil bisa berarti klik yang gagal.
Apa itu Hydration Mismatch
Next.js dengan App Router melakukan dua tahap render: server merender HTML lengkap, lalu browser "menghidupkan" HTML itu dengan React di klien (proses ini disebut hydration). Mismatch terjadi ketika HTML server berbeda dari yang React ingin render di klien. Penyebab umum: pemakaian Date.now(), Math.random(), window.innerWidth, atau API browser yang tidak tersedia di server. Dokumentasi lengkapnya tersedia di Next.js docs hydration error.
Ketika ada mismatch, React versi 18+ akan re-render seluruh subtree di klien untuk memperbaikinya. Re-render itulah yang menyebabkan layout shift, dan akhirnya skor CLS memburuk.
Tanda-Tanda Hydration Mismatch di Web Vitals
| Sinyal | Lokasi | Indikator |
|---|---|---|
| CLS spike | CrUX atau PageSpeed Insights | CLS > 0,1 di mobile |
| Console warning | DevTools, tab Console | "Text content did not match" |
| Layout flash | DevTools, tab Performance | Layout shift di awal load |
| INP memburuk | Field data CrUX | INP > 200 ms |
Studi Kasus: Atmo dan Tombol Login yang Loncat
Saat membangun Atmo, platform LMS, kami punya tombol login di header yang state-nya bergantung apakah user sudah authenticated. Awalnya kami pakai pola sederhana: useEffect yang membaca cookie token, lalu render label "Login" atau "Dashboard" sesuai hasilnya.
Hasilnya, server selalu render "Login" karena tidak punya akses cookie pengguna. Klien lalu re-render dengan "Dashboard" untuk user yang sudah login. Selisih lebar dua label itu cuma 30-40 piksel, tapi cukup untuk membuat CLS field data naik dari 0,05 ke 0,18.
Kami memperbaikinya dengan menyamakan render server dan klien menggunakan placeholder skeleton dengan lebar fixed selama hydration belum selesai, lalu swap dengan label asli. CLS kembali ke 0,04 dalam dua minggu setelah deploy. Angka ini bervariasi tergantung kompleksitas komponen, tapi pola fixnya konsisten.
Tiga Penyebab Paling Sering
Pertama, akses ke window atau document di top-level komponen. Server tidak punya window, jadi kode itu akan throw atau menghasilkan output berbeda. Solusi: bungkus dalam useEffect atau cek typeof window !== 'undefined'.
Kedua, render kondisional berbasis user agent atau cookie tanpa SSR-aware library. Pola "deteksi mobile via window.innerWidth" hampir selalu menghasilkan mismatch. Solusi: gunakan CSS media query atau library seperti @vercel/edge yang punya akses request headers di edge runtime.
Ketiga, format tanggal atau angka berbeda antara server dan klien. Server biasanya pakai locale UTC, klien pakai locale browser. Solusi: pakai library seperti date-fns dengan locale eksplisit, atau format di server saja dengan toLocaleString('id-ID', ...) yang konsisten.
Pertanyaan Umum
Apakah hydration mismatch hanya masalah di Next.js?
Tidak. Setiap framework dengan SSR atau SSG punya potensi mismatch, termasuk Remix, Nuxt, dan Astro. Polanya sama: HTML server berbeda dengan render klien.
Apakah hydration mismatch berdampak ke SEO?
Tidak langsung ke ranking, tapi berdampak ke Core Web Vitals. Skor CLS yang buruk adalah faktor pendukung peringkat sejak Page Experience update.
Bagaimana cara cek hydration mismatch di production?
Tiga cara: install Vercel Speed Insights, gunakan Sentry untuk track React errors, atau aktifkan logging custom di app/layout.tsx yang capture event console.error dari React.
Apakah suppressHydrationWarning solusi yang aman?
Hanya untuk kasus spesifik seperti timestamp atau ID acak yang memang harus berbeda. Untuk konten utama, jangan dipakai sebagai workaround. Bug-nya akan tetap ada, hanya warning-nya yang hilang.
Audit dalam Satu Sore
Buka DevTools, tab Console, lalu navigasi ke setiap halaman utama website Anda. Kalau ada warning "Hydration failed" atau "Text content did not match", catat halamannya. Setelah itu cek CrUX Dashboard untuk halaman tersebut. Korelasi antara warning dan CLS tinggi biasanya cukup jelas. Itu titik awal perbaikan yang paling murah dampaknya pada konversi.
Artikel Terkait
Website Bisnis
Cara Marketer Indonesia Pasang CSS field-sizing: content di Next.js untuk Form Kontak, Pangkas 6 KB Library Autosize dan Hilangkan Hydration Mismatch SSR di 2026
Pasang field-sizing: content di Next.js untuk auto-resize textarea tanpa JS. Hemat 6 KB autosize, hilangkan hydration mismatch SSR, dan jaga INP stabil di form panjang.
Website Bisnis
Cara Marketer Indonesia Pasang CSS light-dark() di Next.js untuk Dark Mode Otomatis, Pangkas 38 Baris Media Query dan Hilangkan Hydration Mismatch Theme di 2026
Ganti next-themes dual class jadi 1 fungsi CSS. Studi kasus Vetmo: bundle CSS turun 24%, LCP membaik 180 ms, dan hydration mismatch dark mode hilang total.
Website Bisnis
Cara Marketer Indonesia Pasang CSS reading-flow di Next.js untuk Layout Flex dan Grid, Sinkronkan Urutan Tab dengan Visual dan Lulus Audit WCAG 2.2 di 2026
Pasang CSS reading-flow di Next.js untuk menyamakan urutan keyboard tab dengan layout visual. Hilangkan tabindex manual dan lulus audit WCAG 2.2 level AA.
Butuh website yang benar-benar bekerja?
Hubungi Vito untuk konsultasi gratis 15 menit.
WhatsApp Sekarang