Memahami Apa yang Terjadi Saat UI Tidak Sinkron

Diagnosa Hydration Mismatch di SvelteKit berfokus pada masalah ketika hasil render server berbeda dengan yang dirender di client setelah hydration. Akibatnya komponen bisa kehilangan event handler, menampilkan markup yang berbeda, atau bahkan crash saat mengeksekusi lifecycle. Dalam 1-2 paragraf pertama ini sudah jelas bahwa solusi melibatkan pemeriksaan data SSR, match props, dan debugging store agar server dan client menghasilkan UI yang sama.

Solusi praktisnya melibatkan inspeksi nilai dari load di server, pengujian ulang data saat hydrated di client, serta memastikan tidak ada logic yang hanya berjalan di client yang mengubah DOM secara berbeda.

Gejala Render Berbeda Antara Server dan Client

Hydration mismatch tampak ketika browser menampilkan peringatan seperti “Text content does not match server-rendered HTML” di console. Gejala lain termasuk:

  • Komponen berisi nilai berbeda setelah hydration (misal daftar kosong di server tapi ada item di client).
  • Event handler tidak terpasang karena DOM berbeda.
  • State store yang awalnya terisi di client mengalami perubahan instan saat hydration selesai.

Penting untuk memeriksa juga apakah ada atribut dinamis (seperti class atau aria-*) yang dihasilkan beda antara render server dan client karena branching conditional yang bergantung pada window atau API browser lainnya.

Langkah Diagnosa dan Reproduksi Masalah

1. Reproduksi dengan Data Statis

Mulai dari kondisi simplest: buat page dengan data statis via load yang mengembalikan JSON tetap. Kemudian lihat apakah markup sama pada server dan client dengan menjalankan npm run dev dan memeriksa view source atau server-side HTML.

2. Cek Konsistensi Proses Fetch dan Store

Jika load mengakses API, pastikan nilai akhir yang disimpan ke store sama sebelum dan sesudah hydration. Tambahkan console.log di +page.server.ts dan di client-side script untuk membandingkan data.

export const load = async ({ fetch }) => {
  const response = await fetch('/api/items');
  const items = await response.json();
  console.log('server items', items);
  return { items };
};

// +page.svelte

{#each data.items as item}
  
{item}
{/each}

Perhatikan bahwa log client tidak akan muncul sampai hydration selesai. Jika nilainya berbeda, pastikan tidak ada proses asynchronous tambahan di client yang memodifikasi data sebelum render akhir.

Debugging Store dan Strategi Konsistensi

Mengecek Store Global

Gunakan store Svelte (misalnya writable) hanya setelah data server dipastikan sama. Hindari inisialisasi store di client yang mengubah nilai default saat hydration. Jika store perlu diisi ulang di client (misalnya berdasarkan window), lakukan update di onMount agar tidak mengganggu markup awal.

Menjaga Konsistensi Props dan Atribut

Periksa komponen yang menerima props dari server. Pastikan nilai tersebut tidak dimodifikasi langsung di komponen (misalnya dengan let value = prop dan diubah tanpa reaktivitas). Gunakan pattern immutable atau update reaktif agar Svelte tahu bahwa nilai tersebut tidak berubah secara diam-diam.

Contoh kasus: atribut boolean yang terkondisi di server tetapi bergantung pada ukuran viewport di client. Solusi: tetapkan nilai default berdasarkan data server, lalu jika perlu sesuaikan di onMount atau event, dan gunakan binding yang konsisten.

Tips Testing dan Debugging Lanjutan

Beberapa pendekatan untuk memastikan tidak ada mismatch:

  • Gunakan npm run test dengan Playwright atau Cypress untuk memeriksa UI setelah hydration—tekan snapshot awal dan bandingkan DOM.
  • Aktifkan logging di middleware SvelteKit untuk melihat payload load di server dan periksa apakah nilainya cocok dengan data yang tiba di client.
  • Gunakan opsi client:only pada komponen jika benar-benar tidak bisa disinkronkan, tetapi ini menonaktifkan SSR untuk bagian tersebut.

Jangan lupa untuk memeriksa perbedaan locale atau timezone data yang bisa menyebabkan mismatch saat menampilkan tanggal.

Ringkasan dan Checklist

Diagnosa secara sistematis:

  1. Pastikan yang server render sama dengan hydrate candidate: periksa log load dan props.
  2. Hindari branching yang bergantung pada API browser saat render server.
  3. Gunakan onMount untuk logic yang hanya boleh dijalankan di client.
  4. Bangun suite testing UI setelah hydration dengan Playwright atau Cypress.

Dengan mengikuti langkah-langkah ini, Anda dapat mengidentifikasi dan memperbaiki sumber hydration mismatch di SvelteKit secara konkret.