Render mismatch terjadi ketika markup HTML yang dihasilkan oleh Laravel di sisi server tidak cocok dengan hasil hydrating JavaScript di browser. Gejalanya antara lain UI berkedip, komponen Inertia/Livewire mengulang render, atau warning "Hydration mismatch" di konsol. Dalam 1–2 menit awal percobaan, Anda sebaiknya langsung membandingkan output HTML yang diterima klien dengan markup server untuk menghindari asumsi keliru.

Artikel ini fokus memetakan diagnosis hash/checksum, penyebab data tidak sinkron, dan langkah memperbaiki response SSR agar hydrating berjalan mulus. Pendekatan ini berlaku untuk stack Laravel + Blade + (Inertia/Livewire) yang mengandalkan state awal untuk membangun UI di sisi klien.

Gejala Render Mismatch pada Laravel Hydration SSR

Gejala pertama yang mudah dilihat adalah komponen JavaScript melakukan re-render tambahan setelah halaman dimuat sementara markup awal sudah tampil. Bisa juga muncul perbedaan teks atau atribut yang menyebabkan interaksi awal tidak berfungsi, misalnya tombol menu tidak muncul padahal server sudah mengirimkannya. Jika Anda melihat warning "Hydration mismatch" di console browser, itu berarti DOM server dan DOM klien tidak identik.

Render mismatch sering disebabkan oleh state awal yang tidak konsisten: data yang di-inject melalui Inertia::share, model Livewire yang berubah saat rendering, atau nilai default props yang berbeda antara server dan klien. Di halaman yang kompleks, mismatch juga terasa lewat layout yang tiba-tiba berubah setelah JavaScript mengambil alih.

Diagnosis: Membandingkan Markup dan State

Inspect HTML ter-render server vs klien

Langkah pertama adalah memeriksa markup yang dikirim server dan hasil akhir di browser. Gunakan View Source untuk melihat HTML SSR utuh, lalu bandingkan dengan DOM Inspector setelah hydration selesai. Cari perbedaan atribut, class, atau teks yang menjadi indikator bahwa data yang di-fetch berbeda atau komponen mengalami re-render.

Periksa checksum dan data state

Beberapa stack seperti Inertia menyertakan checksum atau payload JSON di dalam markup untuk memvalidasi data. Pastikan nilai checksum di HTML server cocok dengan payload yang dibaca oleh klien. Jika tidak, browser mungkin memaksa re-render ulang. Untuk Livewire, periksa payload serverMemo yang menyertakan state awal; mismatch di sini berarti state sudah berubah di tengah render.

Gunakan logging untuk data yang dikirim

Tambahkan log sementara di controller agar Anda tahu data apa yang dikirimkan ke view. Misalnya Log::debug('SSR props', $props) sebelum mengembalikan Inertia::render. Dengan cara ini, Anda bisa membandingkan isi data dengan state yang diharapkan di klien, terutama jika proses load tergantung middleware atau session.

Penyebab Umum Render Mismatch

  • Default props berbeda: Inertia atau komponennya memiliki nilai default yang tidak sama dengan state server. Saat hydration, JavaScript mengganti nilai dengan defaultnya dan menciptakan mismatch.
  • Waktu fetching asynchronous: Data yang di-fetch setelah response disusun, misalnya menggunakan useEffect atau Livewire yang memanggil kembali render() secara otomatis, menyebabkan markup klien berubah.
  • Middleware atau guard mengubah respons: Middleware autentikasi atau izin bisa menyisipkan data lain, misalnya user role, yang tidak konsisten di setiap permintaan.
  • State global yang berubah: Session atau cache yang diperbarui saat middleware dijalankan dapat membuat JSON payload berbeda, sementara markup server sudah di-render dengan nilai lama.

Karena perbedaan ini sering muncul hanya pada environment tertentu (misalnya session pengguna masih kosong), jangan hanya mengandalkan developer mode; selalu cek log dan payload di situasi produksi atau staging dengan data nyata.

Menjaga Konsistensi SSR Response

Tujuan utama adalah agar markup server dan state klien memiliki satu sumber kebenaran. Berikut praktik yang membantu:

  • Sinkronkan data response: Pastikan controller mengirim data yang sama persis ke view dan ke payload JSON. Hindari manipulasi data lebih lanjut di middleware setelah response terbuat.
  • Kunci state reactivity: Jika menggunakan Livewire, jangan ubah $listeners atau properti publik setelah render pertama tanpa alasan. Jika perlu perubahan, lakukan di lifecycle yang jelas seperti mount() sebelum pertama kali render.
  • Invalidate cache secara eksplisit: Jika response bergantung pada cache (misalnya user preference), pastikan header cache dan invalidation dikontrol agar klien tidak menerima versi lama.

Contoh Controller Konsisten untuk Inertia SSR

public function show(DashboardQuery $query)
{
    $data = $query->handle(); // Variabel data hanya sekali dihitung

    return Inertia::render('Dashboard/Index', [
        'stats' => $data->stats,
        'recentActivity' => $data->recentActivity,
        'user' => Auth::user()->only(['id', 'name', 'role']),
    ]);
}

Contoh di atas memastikan data hanya diambil sekali sebelum Inertia::render. Dengan menggunakan accessor seperti only, Anda menetapkan bentuk payload secara deterministik sehingga markup Blade dan payload JSON klien sejajar.

Observabilitas dan Validasi Hydration

Periksa log Laravel untuk melihat apakah controller memberikan data yang diharapkan, termasuk middleware yang ikut menyisipkan nilai. Gunakan Laravel Telescope untuk melihat request/response detail dan memeriksa payload Inertia/Livewire. Telescope juga membantu melihat apakah ada exception saat hydration.

Di browser, gunakan DevTools Network untuk memeriksa JSON response dari endpoint SSR. Jika payload berubah setelah hydration (misalnya data baru dikirim melalui API), pastikan perubahan tersebut diantisipasi sebagai update client-side, bukan mismatch awal.

Debugging tips lain: tambahkan console.log di entry JavaScript untuk menampilkan payload state saat mounted. Jika log menunjukkan data berbeda dari markup awal, fokus pada bagian backend yang memodifikasi state setelah render.

Dengan pendekatan ini, Anda tidak hanya mendeteksi render mismatch lebih cepat, tapi juga membangun pipeline SSR yang stabil, sekaligus memberi tim observabilitas yang cukup untuk bereaksi terhadap perubahan data nyata.