Setiap halaman web yang lo buka adalah hasil satu keputusan arsitektur yang jarang kelihatan: HTML-nya diracik di server atau di browser. Menurut MDN, server-side rendering adalah praktik menghasilkan HTML di server lalu mengirimkannya ke klien, sedangkan client-side rendering menghasilkan HTML memakai JavaScript di browser. Google lewat web.dev justru menyarankan developer mempertimbangkan SSR atau rendering statis ketimbang pendekatan full rehydration. Artikel ini membedah cara kerja keduanya, posisi hydration di tengahnya, dan angka TTFB dari situs ini sendiri yang jalan di Astro 7.3.2 dengan output server.
TL;DR
- SSR meracik HTML di server lalu mengirimkannya ke browser; CSR meracik HTML di browser memakai JavaScript.
- Hydration adalah proses JavaScript menempel ke HTML hasil server. React mensyaratkan hasil render klien identik dengan server, kalau beda muncul hydration mismatch.
- Situs ini jalan di Astro 7.3.2 dengan output server: 11 dari 19 halaman di-prerender, sisanya dirender on-demand per request.
- TTFB render SSR di origin terukur 10,2 sampai 27,2 ms untuk 54.413 byte HTML, sedangkan halaman prerender 2,5 sampai 10,2 ms.
- Jebakan produksi yang nyata: menukar direktori build tanpa restart proses tetap menyajikan bundle lama, karena HTML diracik ulang tiap request.
Apa perbedaan SSR, CSR, dan rendering statis?
Perbedaannya ada di lokasi HTML diracik, bukan di kerumitan aplikasinya. MDN mendefinisikan SSR sebagai praktik menghasilkan HTML di server dan mengirimkannya ke klien, sementara CSR menghasilkan HTML di browser memakai JavaScript. Keduanya, menurut catatan MDN yang sama, tidak saling meniadakan dan bisa dipakai bersamaan dalam satu aplikasi.
web.dev memberi kerangka yang lebih lengkap karena membedakan empat pendekatan, bukan dua. Server-side rendering berarti aplikasi diracik di server supaya yang dikirim ke klien adalah HTML, bukan JavaScript. Client-side rendering berarti aplikasi diracik di browser, dengan JavaScript memodifikasi DOM. Prerendering berarti menjalankan aplikasi sisi klien saat build time untuk menangkap keadaan awalnya sebagai HTML statis. Terakhir, ada rehydration, yaitu menjalankan JavaScript di klien untuk mengubah halaman statis menjadi aplikasi dinamis.
Perbedaan istilah ini bukan urusan akademis, karena biayanya beda-beda. Pada CSR, browser menerima dokumen yang isinya nyaris kosong lalu menunggu JavaScript selesai diunduh, diparse, dan dijalankan sebelum ada konten berarti. Pada SSR, browser sudah menerima HTML jadi sehingga bisa langsung menampilkan teks, tapi server ikut menanggung pekerjaan meracik halaman pada setiap request. Pada prerendering, pekerjaan itu dipindahkan ke build time, jadi tidak ada server yang dihitung per request, dengan konsekuensi isi halaman tidak bisa berubah setelah build.
Karena itu klaim yang sering beredar, bahwa SSR otomatis lebih cepat dari CSR, tidak tepat sebagai aturan umum. Yang berubah adalah kapan dan di mana biayanya dibayar. CSR membayar di perangkat pengguna, SSR membayar di server, dan prerendering membayar sekali saat build.
Bagaimana hydration bekerja dan kenapa rawan?
Hydration adalah jembatan antara HTML statis dan aplikasi yang hidup. Dokumentasi React menjelaskan bahwa fungsi hydrateRoot dipakai untuk menempelkan React ke HTML yang sudah ada, HTML yang sebelumnya dirender oleh React di lingkungan server. Sebelum hydration jalan, halaman yang lo lihat cuma gambar mati: teksnya terbaca, tapi belum ada event handler yang menempel.
Titik rawannya ada di situ. Dokumentasi React menyatakan pohon komponen yang dilewatkan ke hydrateRoot harus menghasilkan output yang sama seperti waktu dirender di server. Alasannya bukan soal estetika: pengguna sempat melihat HTML hasil server sebelum JavaScript selesai dimuat, dan server rendering menciptakan ilusi aplikasi memuat lebih cepat. Begitu konten yang muncul berbeda, ilusi itu langsung patah.
Yang membuat masalah ini mahal adalah bentuk kegagalannya. React bisa pulih dari sebagian hydration error, tapi dokumentasinya tetap menyebutnya harus diperbaiki seperti bug lain. Pada kasus terbaik, hydration error cuma bikin halaman melambat. Pada kasus terburuk, event handler bisa menempel ke elemen yang salah, sehingga tombol terlihat normal tapi yang terjadi saat diklik bukan yang lo harapkan.
Ada juga jebakan biaya yang jarang dibahas: hydration adalah pekerjaan JavaScript di perangkat pengguna. Semakin banyak komponen yang perlu dihidupkan, semakin berat beban di ponsel kelas bawah. Ini yang membuat web.dev menulis bahwa developer sebaiknya mempertimbangkan server-side rendering atau rendering statis ketimbang pendekatan full rehydration. Rekomendasi itu bukan penolakan terhadap JavaScript, melainkan penolakan terhadap JavaScript yang dijalankan untuk semua bagian halaman, termasuk bagian yang sebenarnya tidak interaktif.
Di mana hydration mismatch paling sering muncul?
Penyebabnya jarang yang eksotis. Dokumentasi React mendaftar empat sumber yang paling sering, dan semuanya berakar pada satu hal: nilai yang berbeda antara render server dan render klien. Pertama, spasi tambahan seperti baris baru di sekitar HTML yang dihasilkan React di dalam node akar. Kedua, pemakaian pemeriksaan seperti typeof window pada logika rendering, karena window tidak ada di server. Ketiga, pemakaian API khusus browser seperti window.matchMedia di logika rendering. Keempat, merender data yang berbeda di server dan di klien.
Pola keempat yang paling sering lolos ke produksi, dan biasanya bentuknya halus. Contoh tipikalnya waktu: server merender dalam zona waktu UTC sementara browser pengguna di WIB, lalu stempel waktu yang tampil berbeda tujuh jam. Kedua sisi sebenarnya menjalankan kode yang sama, tapi masukannya berbeda, jadi hasilnya berbeda. Cara mendeteksinya bukan dengan membaca kode lebih lama, melainkan dengan membandingkan HTML hasil server dan hasil render klien pada input yang sama.
Konsekuensi praktisnya: hydration bukan sekadar soal kecepatan, tapi soal kebenaran. Halaman yang terlihat benar bisa saja punya tombol yang menempel ke handler yang salah, dan itu jenis bug yang tidak ketahuan dari screenshot.
Bagaimana perbandingan tiap pendekatan rendering?
Tabel berikut merangkum empat pendekatan berdasarkan kerangka yang dipakai web.dev, ditambah kolom konsekuensi operasional yang muncul saat dijalankan di produksi.
| Pendekatan | HTML diracik di | Biaya per request | Isi bisa berubah? | Cocok untuk |
|---|---|---|---|---|
| CSR | Browser | Berat di perangkat pengguna | Ya, semuanya di klien | Aplikasi di balik login, dashboard internal |
| SSR | Server | Ada, dihitung tiap request | Ya, tiap request | Konten yang berubah dan perlu terindeks |
| Prerendering statis | Build time | Nol render | Tidak, sampai build berikutnya | Halaman kebijakan, halaman statis, landing |
| ISR atau revalidasi | Build time plus refresh | Render berkala | Ya, dengan jeda | Katalog besar yang jarang berubah |
Yang perlu dicatat dari tabel itu: tidak ada kolom yang menang di semua baris. SSR menang di kesegaran isi, prerendering menang di biaya per request, dan CSR menang saat seluruh halaman memang butuh state klien. Kombinasi keduanya dalam satu situs bukan tanda arsitektur berantakan, justru itu yang disarankan.
Apa yang terukur di situs ini?
Situs ini jadi contoh yang bisa diperiksa karena konfigurasinya terbuka. Astro dijalankan pada versi 7.3.2 dengan output server dan adapter node dalam mode standalone. Artinya seluruh halaman dirender on-demand secara default, lalu sebagian halaman dikembalikan ke mode statis secara eksplisit lewat prerender. Dari 19 halaman, 11 memakai prerender, termasuk halaman tentang, kontak, dan beberapa halaman tools. Sisanya, termasuk seluruh artikel blog, dirender per request.
Pengukuran TTFB dilakukan langsung ke origin lewat loopback supaya angka yang terukur adalah biaya rendering, bukan biaya jaringan. Enam kali permintaan ke satu halaman artikel menghasilkan TTFB antara 10,2 ms dan 27,2 ms untuk 54.413 byte HTML. Halaman yang di-prerender, pada perbandingan yang sama, berada di 2,5 ms sampai 10,2 ms untuk 16.879 byte. Selisihnya masuk akal: halaman SSR membayar pekerjaan meracik, halaman statis cuma mengirim berkas yang sudah jadi.
Untuk gambaran yang lebih jujur, angka itu belum termasuk jaringan. Permintaan yang sama lewat CDN publik mencatat TTFB sekitar 102 ms, jadi pulang pergi ke edge menyumbang bagian terbesar, sementara biaya rendering servernya di kisaran puluhan milidetik. Kesimpulan praktisnya: pada situs sekecil ini, mempercepat rendering server bukan pengungkit terbesar. Yang lebih menentukan adalah jarak pengguna ke edge dan seberapa banyak JavaScript yang harus dihidupkan di perangkat mereka.
Ambang yang dipakai untuk menilai hasilnya juga bukan karangan. Largest Contentful Paint dinilai baik kalau 2,5 detik atau kurang, diukur pada persentil ke-75 beban halaman yang dipisah antara mobile dan desktop. Interaction to Next Paint dinilai baik kalau 200 ms atau kurang, dan disebut buruk kalau di atas 500 ms. Cumulative Layout Shift dinilai baik kalau 0,1 atau kurang, dan buruk kalau di atas 0,25. Ketiganya metrik lapangan, bukan hasil uji lab.
Kapan SSR layak dipakai dan kapan cukup statis?
Pertanyaan penentunya sederhana: apakah isi halaman ini perlu berbeda untuk setiap request? Kalau jawabannya tidak, SSR hanya menambah pekerjaan server tanpa menambah nilai. Dokumentasi Astro bahkan menyarankan mulai dari mode statis sampai yakin bahwa sebagian besar halaman memang butuh dirender on-demand, dengan alasan supaya situs tetap seperformat mungkin dan tidak bergantung pada fungsi server untuk merender konten statis.
Kalau jawabannya ya, pertanyaan berikutnya adalah siapa yang menanggung biayanya. SSR yang dipakai untuk menampilkan konten yang berubah dan perlu terindeks adalah pertukaran yang masuk akal. SSR yang dipakai untuk menampilkan satu angka acak di halaman yang isinya sama sepanjang tahun adalah biaya yang dibayar tiap request tanpa manfaat.
Ada satu konsekuensi operasional yang sering luput dari diskusi arsitektur, dan ini kami alami sendiri. Karena HTML diracik ulang tiap request, proses server memegang kode aplikasi di memorinya. Menukar direktori hasil build di disk tidak otomatis membuat proses yang sedang jalan memakai kode baru. Gejalanya menipu: berkas di disk sudah versi terbaru, tapi yang dilayani ke pengunjung masih versi lama, sehingga perbaikan yang sudah di-deploy seolah tidak berefek. Urutan yang benar adalah menukar direktori build lalu me-restart proses secara eksplisit, dan itu harus jadi bagian dari pipeline deploy, bukan langkah manual yang diingat-ingat.
Sumber & Referensi
- MDN, Server-side rendering (SSR), definisi SSR dan hubungannya dengan client-side rendering.
- MDN, Client-side rendering (CSR), definisi CSR sebagai lawan SSR.
- web.dev, Rendering on the Web, kerangka istilah SSR, CSR, prerendering, dan rehydration beserta trade-off performanya.
- React, hydrateRoot, kontrak hydration, daftar penyebab hydration error, dan bentuk kegagalannya.
- Astro Docs, On-demand rendering, perilaku output server dan penggunaan prerender untuk halaman statis.
- web.dev, Largest Contentful Paint, ambang LCP dan dasar pengukuran pada persentil ke-75.
- web.dev, Interaction to Next Paint, ambang INP dan pembagian kategori responsivitas.
- web.dev, Cumulative Layout Shift, ambang CLS dan batas nilai yang dianggap buruk.
FAQ
Apakah SSR selalu lebih cepat daripada CSR?
Tidak selalu, karena yang berubah adalah lokasi biayanya, bukan besar biayanya. SSR memindahkan pekerjaan meracik halaman ke server sehingga pengguna lebih cepat melihat konten, tapi server harus mengerjakannya pada setiap request. Kalau halaman itu isinya tidak berubah dan tidak perlu dirender ulang, rendering statis atau prerendering biasanya lebih murah untuk hasil yang sama.
Kenapa halaman yang sudah benar bisa tetap kena hydration error?
Karena masalahnya bukan di kode yang salah, melainkan di nilai yang berbeda antara server dan klien. Dokumentasi React menyebut empat penyebab tersering, termasuk spasi tambahan di dalam node akar, pemeriksaan yang hanya ada di browser, API khusus browser di logika rendering, dan data yang berbeda di kedua sisi. Semuanya menghasilkan output yang berbeda, dan itu yang memicu error.
Apa risiko terburuk dari hydration mismatch?
Pada kasus terbaik, hydration error hanya memperlambat halaman. Pada kasus terburuk, event handler bisa menempel ke elemen yang salah, sehingga tombol tampak normal tapi aksi yang dijalankan bukan yang diharapkan pengguna. Karena itu React menyebut hydration error harus diperbaiki seperti bug biasa, bukan dibiarkan karena halaman masih terlihat benar.
Apakah situs harus dirender per request supaya bisa terindeks mesin pencari?
Tidak, dan ini kekeliruan yang mahal. Rendering statis sudah mengirimkan HTML penuh ke crawler, jadi halaman yang di-prerender tetap bisa terindeks. Yang perlu HTML utuh di response pertama adalah halaman yang isinya berubah dan perlu diperbarui tanpa build ulang. Untuk halaman yang jarang berubah, prerendering memberi hasil indeks yang sama dengan biaya server yang lebih kecil.
Bagaimana cara tahu biaya rendering server saya sendiri?
Ukur langsung ke origin, bukan lewat CDN, supaya angka yang keluar adalah biaya rendering dan bukan biaya jaringan. Cara termudah adalah mengukur time to first byte berulang kali pada satu halaman dinamis lalu membandingkannya dengan satu halaman statis di server yang sama. Selisih keduanya adalah perkiraan biaya render per request di lingkungan itu.
Rekomendasi Tools & Layanan
Beberapa layanan yang dipake di panduan ini: free trial Alibaba Cloud (coba gratis, sesuaikan kebutuhan), dan halaman promo terbaru buat cek diskon yang lagi jalan bulan ini.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬