Dipublikasikan: 6 Februari 2019, Terakhir diperbarui: 5 Januari 2026
Salah satu keputusan inti yang harus dibuat oleh developer web adalah tempat untuk menerapkan logika dan rendering dalam aplikasi mereka. Hal ini bisa jadi sulit karena ada begitu banyak cara untuk membuat situs.
Pemahaman kami tentang ruang ini didasarkan pada pekerjaan kami di Chrome yang berinteraksi dengan situs besar selama beberapa tahun terakhir. Secara umum, kami mendorong developer untuk mempertimbangkan rendering sisi server atau rendering statis daripada pendekatan rehidrasi penuh.
Untuk lebih memahami arsitektur yang kita pilih saat membuat keputusan ini, kita memerlukan terminologi yang konsisten dan framework bersama untuk setiap pendekatan. Kemudian, Anda dapat mengevaluasi konsekuensi dari setiap pendekatan rendering dengan lebih baik dari perspektif performa halaman.
Terminologi
Pertama, kita tentukan beberapa terminologi yang akan kita gunakan.
Rendering
- Rendering sisi server (SSR)
- Merender aplikasi di server untuk mengirim HTML, bukan JavaScript, ke klien.
- Rendering sisi klien (CSR)
- Merender aplikasi di browser, menggunakan JavaScript untuk mengubah DOM.
- Pra-rendering
- Menjalankan aplikasi sisi klien pada waktu build untuk mengambil status awalnya sebagai HTML statis. Perhatikan bahwa "pra-rendering" dalam hal ini berbeda dengan pra-rendering browser untuk navigasi mendatang.
- Hidrasi
- Menjalankan skrip sisi klien untuk menambahkan status aplikasi dan interaktivitas ke HTML yang dirender server. Hidrasi mengasumsikan DOM tidak berubah.
- Rehidrasi
- Meskipun sering digunakan untuk mengartikan hal yang sama dengan hidrasi, rehidrasi berarti memperbarui DOM secara rutin dengan status terbaru, termasuk setelah hidrasi awal.
Performa
- Time to First Byte (TTFB)
- Waktu antara mengklik link dan byte pertama konten yang dimuat di halaman baru.
- First Contentful Paint (FCP)
- Waktu saat konten yang diminta (teks artikel, dll.) terlihat.
- Interaction to Next Paint (INP)
- Metrik representatif yang menilai apakah halaman secara konsisten merespons input pengguna dengan cepat.
- Total Blocking Time (TBT)
- Metrik proxy untuk INP yang menghitung durasi pemblokiran thread utama selama pemuatan halaman.
Rendering sisi server
Rendering sisi server menghasilkan HTML lengkap untuk halaman di server sebagai respons terhadap navigasi. Hal ini menghindari perjalanan bolak-balik tambahan untuk pengambilan data dan pembuatan template di klien, karena perender menanganinya sebelum browser mendapatkan respons.
Rendering sisi server umumnya menghasilkan FCP yang cepat. Menjalankan logika halaman dan rendering di server memungkinkan Anda menghindari pengiriman banyak JavaScript ke klien. Hal ini membantu mengurangi TBT halaman, yang juga dapat menyebabkan INP yang lebih rendah, karena thread utama tidak terlalu sering diblokir selama pemuatan halaman. Jika thread utama lebih jarang diblokir, interaksi pengguna memiliki lebih banyak peluang untuk berjalan lebih cepat.
Hal ini masuk akal, karena dengan rendering sisi server, Anda benar-benar hanya mengirim teks dan link ke browser pengguna. Pendekatan ini dapat berfungsi dengan baik untuk berbagai kondisi perangkat dan jaringan serta membuka pengoptimalan browser yang menarik, seperti penguraian dokumen streaming.
Dengan rendering sisi server, pengguna cenderung tidak perlu menunggu JavaScript yang terikat CPU berjalan sebelum dapat menggunakan situs Anda. Meskipun Anda tidak dapat menghindari JavaScript pihak ketiga, menggunakan rendering sisi server untuk mengurangi biaya JavaScript pihak pertama Anda sendiri dapat memberi Anda lebih banyak anggaran untuk sisanya. Namun, ada satu potensi konsekuensi dari pendekatan ini: membuat halaman di server memerlukan waktu, yang dapat meningkatkan TTFB halaman Anda.
Apakah rendering sisi server sudah cukup untuk aplikasi Anda, sebagian besar bergantung pada jenis pengalaman yang Anda bangun. Ada perdebatan yang sudah lama berlangsung tentang penerapan yang benar antara rendering sisi server versus rendering sisi klien, tetapi Anda selalu dapat memilih untuk menggunakan rendering sisi server untuk beberapa halaman dan tidak untuk halaman lainnya. Beberapa situs telah berhasil menerapkan teknik rendering hybrid. Misalnya, Netflix merender halaman landing yang relatif statis di sisi server, sekaligus prefetching JavaScript untuk halaman yang memerlukan banyak interaksi, sehingga halaman yang dirender di sisi klien yang lebih berat ini memiliki peluang lebih besar untuk dimuat dengan cepat.
Dengan banyak framework, library, dan arsitektur modern, Anda dapat merender aplikasi yang sama di klien dan server. Anda dapat menggunakan teknik ini untuk rendering sisi server. Namun, arsitektur yang melakukan rendering di server dan di klien merupakan kelas solusi tersendiri dengan karakteristik performa dan konsekuensi yang sangat berbeda. Pengguna React dapat menggunakan API DOM server atau solusi yang dibuat di atasnya seperti Next.js untuk rendering sisi server. Pengguna Vue dapat menggunakan panduan rendering sisi server Vue atau Nuxt. Angular memiliki Universal.
Namun, sebagian besar solusi populer menggunakan beberapa bentuk hidrasi, jadi perhatikan pendekatan yang digunakan alat Anda.
Rendering statis
Rendering statis terjadi pada waktu build. Pendekatan ini menawarkan FCP yang cepat, serta TBT dan INP yang lebih rendah, asalkan Anda membatasi jumlah JavaScript sisi klien di halaman Anda. Tidak seperti rendering sisi server, rendering ini juga mencapai TTFB yang cepat secara konsisten, karena HTML untuk halaman tidak harus dibuat secara dinamis di server. Secara umum, rendering statis berarti menghasilkan file HTML terpisah untuk setiap URL sebelumnya. Dengan respons HTML yang dihasilkan sebelumnya, Anda dapat men-deploy render statis ke beberapa CDN untuk memanfaatkan edge caching.
Solusi untuk rendering statis tersedia dalam berbagai bentuk dan ukuran. Alat seperti Gatsby dirancang untuk membuat developer merasa seolah-olah aplikasi mereka dirender secara dinamis, bukan dibuat sebagai langkah build. Alat pembuatan situs statis seperti 11ty, Jekyll, dan Metalsmith memanfaatkan sifat statisnya, sehingga memberikan pendekatan yang lebih berbasis template.
Salah satu kelemahan rendering statis adalah harus membuat file HTML individual untuk setiap URL yang memungkinkan. Hal ini dapat menjadi tantangan atau bahkan tidak mungkin dilakukan jika Anda perlu memprediksi URL tersebut sebelumnya dan untuk situs dengan banyak halaman unik.
Pengguna React mungkin sudah tidak asing lagi dengan Gatsby, ekspor statis Next.js, atau Navi, yang semuanya memudahkan pembuatan halaman dari komponen. Namun, rendering statis dan pra-rendering berperilaku berbeda: halaman yang dirender secara statis bersifat interaktif tanpa perlu mengeksekusi banyak JavaScript sisi klien, sedangkan pra-rendering meningkatkan FCP Aplikasi Web Satu Halaman yang harus di-booting di klien agar halaman benar-benar interaktif.
Jika Anda tidak yakin apakah solusi tertentu adalah rendering statis atau pra-rendering, coba nonaktifkan JavaScript dan muat halaman yang ingin Anda uji. Untuk halaman yang dirender secara statis, sebagian besar fitur interaktif masih ada tanpa JavaScript. Halaman yang dipra-render mungkin masih memiliki beberapa fitur dasar seperti link dengan JavaScript dinonaktifkan, tetapi sebagian besar halaman tidak aktif.
Pengujian lain yang berguna adalah menggunakan throttling jaringan di Chrome DevTools dan melihat seberapa banyak JavaScript yang didownload sebelum halaman menjadi interaktif. Pra-rendering umumnya memerlukan lebih banyak JavaScript untuk menjadi interaktif, dan JavaScript tersebut cenderung lebih kompleks daripada pendekatan progressive enhancement yang digunakan dalam rendering statis.
Rendering sisi server versus rendering statis
Rendering sisi server bukanlah solusi terbaik untuk semuanya, karena sifatnya yang dinamis dapat menimbulkan biaya overhead komputasi yang signifikan. Banyak solusi rendering sisi server tidak melakukan flush lebih awal, menunda TTFB, atau menggandakan data yang dikirim (misalnya, status inline yang digunakan oleh JavaScript di klien). Di React,
renderToString() bisa lambat karena bersifat sinkron dan single-thread.
DOM API server React yang lebih baru
mendukung streaming, yang dapat mengirimkan bagian awal respons HTML ke
browser lebih cepat, sementara bagian lainnya masih dibuat di server.
Mendapatkan rendering sisi server yang "tepat" dapat melibatkan pencarian atau pembuatan solusi untuk caching komponen, mengelola konsumsi memori, menggunakan teknik memoization, dan masalah lainnya. Anda sering memproses atau membangun ulang aplikasi yang sama dua kali, sekali di klien dan sekali di server. Rendering sisi server yang menampilkan konten lebih cepat tidak selalu mengurangi pekerjaan Anda. Jika Anda memiliki banyak pekerjaan di klien setelah respons HTML yang dihasilkan server tiba di klien, hal ini masih dapat menyebabkan TBT dan INP yang lebih tinggi untuk situs Anda.
Rendering sisi server menghasilkan HTML sesuai permintaan untuk setiap URL, tetapi bisa lebih lambat daripada sekadar menyajikan konten statis yang dirender. Jika Anda dapat melakukan upaya tambahan, rendering sisi server plus caching HTML dapat mengurangi waktu render server secara signifikan. Keuntungan rendering sisi server adalah kemampuan untuk menarik lebih banyak data "live" dan merespons serangkaian permintaan yang lebih lengkap daripada yang mungkin dilakukan dengan rendering statis. Halaman yang memerlukan personalisasi adalah contoh konkret jenis permintaan yang tidak berfungsi dengan baik pada rendering statis.
Rendering sisi server juga dapat memberikan keputusan yang menarik saat membangun PWA. Apakah lebih baik menggunakan caching service worker halaman penuh, atau merender setiap bagian konten di server?
Rendering sisi klien
Rendering sisi klien berarti merender halaman langsung di browser dengan JavaScript. Semua logika, pengambilan data, pembuatan template, dan pemilihan rute ditangani di klien, bukan di server. Hasil efektifnya adalah lebih banyak data yang diteruskan ke perangkat pengguna dari server, dan hal ini memiliki konsekuensi tersendiri.
Rendering sisi klien dapat sulit dibuat dan dipertahankan kecepatannya untuk perangkat seluler.
Dengan sedikit upaya untuk mempertahankan anggaran JavaScript yang ketat
dan memberikan nilai dalam pulang pergi
sesedikit mungkin, Anda dapat membuat rendering sisi klien hampir mereplikasi
performa rendering sisi server murni. Anda dapat membuat parser bekerja
lebih cepat dengan mengirimkan skrip dan data penting menggunakan <link rel=preload>
Sebaiknya pertimbangkan juga untuk menggunakan pola seperti PRPL
untuk memastikan bahwa navigasi awal dan berikutnya terasa instan.
Kelemahan utama rendering sisi klien adalah jumlah JavaScript yang diperlukan cenderung bertambah seiring pertumbuhan aplikasi, yang dapat memengaruhi INP halaman. Hal ini menjadi sangat sulit dengan penambahan library JavaScript baru, polyfill, dan kode pihak ketiga, yang bersaing untuk mendapatkan daya pemrosesan dan sering kali harus diproses sebelum konten halaman dapat dirender.
Pengalaman yang menggunakan rendering sisi klien dan mengandalkan paket JavaScript besar harus mempertimbangkan pemisahan kode yang agresif untuk menurunkan TBT dan INP selama pemuatan halaman, serta pemuatan lambat JavaScript untuk hanya menyajikan apa yang dibutuhkan pengguna, saat dibutuhkan. Untuk pengalaman dengan sedikit atau tanpa interaktivitas, rendering sisi server dapat mewakili solusi yang lebih skalabel untuk masalah ini.
Bagi mereka yang membangun aplikasi web satu halaman, mengidentifikasi bagian inti antarmuka
pengguna yang digunakan bersama oleh sebagian besar halaman memungkinkan Anda menerapkan
teknik caching application shell. Jika digabungkan dengan pekerja layanan, hal ini dapat meningkatkan
performa yang dirasakan secara signifikan pada kunjungan berulang, karena halaman dapat memuat
HTML shell aplikasi dan dependensinya dari CacheStorage dengan sangat cepat.
Rehidrasi menggabungkan rendering sisi server dan sisi klien
Hidrasi adalah pendekatan yang mengurangi konsekuensi antara rendering sisi klien dan sisi server dengan melakukan keduanya. Permintaan navigasi, seperti pemuatan ulang atau pemuatan halaman penuh, ditangani oleh server yang merender aplikasi ke HTML. Kemudian, JavaScript dan data yang digunakan untuk rendering disematkan ke dalam dokumen yang dihasilkan. Jika dilakukan dengan hati-hati, hal ini akan menghasilkan FCP yang cepat seperti rendering sisi server, lalu "melanjutkan" dengan merender lagi di klien.
Ini adalah solusi yang efektif, tetapi dapat memiliki kelemahan performa yang cukup besar.
Kelemahan utama rendering sisi server dengan rehidrasi adalah dapat berdampak negatif yang signifikan pada TBT dan INP, meskipun meningkatkan FCP. Halaman yang dirender sisi server dapat terlihat dimuat dan interaktif, tetapi sebenarnya tidak dapat merespons input hingga skrip sisi klien untuk komponen dijalankan dan pengendali peristiwa telah dilampirkan. Di perangkat seluler, proses ini dapat memerlukan waktu beberapa menit, sehingga membingungkan dan membuat pengguna frustrasi.
Masalah rehidrasi: Satu aplikasi seharga dua aplikasi
Agar JavaScript sisi klien dapat melanjutkan secara akurat dari tempat server berhenti, tanpa meminta ulang semua data yang digunakan server untuk merender HTML-nya, sebagian besar solusi rendering sisi server melakukan serialisasi respons dari dependensi data UI sebagai tag skrip dalam dokumen. Karena proses ini menduplikasi banyak HTML, rehidrasi dapat menyebabkan lebih banyak masalah daripada sekadar interaktivitas yang tertunda.
Server menampilkan deskripsi UI aplikasi sebagai respons terhadap
permintaan navigasi, tetapi juga menampilkan data sumber yang digunakan untuk menyusun
UI tersebut, dan salinan lengkap implementasi UI yang kemudian di-booting di
klien. UI tidak akan menjadi interaktif hingga bundle.js selesai dimuat dan dieksekusi.
Metrik performa yang dikumpulkan dari situs sungguhan yang menggunakan rendering sisi server dan rehidrasi menunjukkan bahwa opsi ini jarang menjadi opsi terbaik. Alasan terpentingnya adalah pengaruhnya terhadap pengalaman pengguna, saat halaman terlihat siap, tetapi tidak ada fitur interaktifnya yang berfungsi.
Ada harapan untuk rendering sisi server dengan rehidrasi. Dalam jangka pendek, hanya menggunakan rendering sisi server untuk konten yang sangat dapat di-cache dapat mengurangi TTFB, sehingga menghasilkan hasil yang serupa dengan pra-rendering. Rehidrasi secara inkremental, progresif, atau parsial mungkin menjadi kunci untuk membuat teknik ini lebih layak di masa mendatang.
Melakukan streaming rendering sisi server dan rehidrasi secara progresif
Rendering sisi server telah mengalami sejumlah perkembangan selama beberapa tahun terakhir.
Streaming rendering sisi server
memungkinkan Anda mengirim HTML dalam potongan-potongan yang dapat dirender secara progresif oleh browser saat
diterima. Hal ini dapat mempercepat pengiriman markup ke pengguna, sehingga mempercepat FCP Anda. Di
React, streaming bersifat asinkron di renderToPipeableStream(), dibandingkan dengan
renderToString() sinkron, yang berarti tekanan balik ditangani dengan baik.
Rehidrasi progresif juga perlu dipertimbangkan (React telah menerapkannya). Dengan pendekatan ini, setiap bagian dari aplikasi yang dirender server akan "di-booting" seiring waktu, bukan pendekatan umum saat ini yang menginisialisasi seluruh aplikasi sekaligus. Hal ini dapat membantu mengurangi jumlah JavaScript yang diperlukan untuk membuat halaman menjadi interaktif, karena memungkinkan Anda menunda upgrade sisi klien pada bagian halaman berprioritas rendah agar tidak memblokir thread utama, sehingga interaksi pengguna dapat terjadi lebih cepat setelah pengguna memulainya.
Rehidrasi progresif juga dapat membantu Anda menghindari salah satu kesalahan rehidrasi rendering sisi server yang paling umum: hierarki DOM yang dirender di sisi server dihancurkan, lalu segera dibuat ulang, paling sering karena rendering sisi klien sinkron awal memerlukan data yang belum siap, sering kali berupa Promise yang belum diselesaikan.
Rehidrasi parsial
Rehidrasi parsial terbukti sulit diterapkan. Pendekatan ini merupakan perluasan dari rehidrasi progresif yang menganalisis setiap bagian halaman (komponen, tampilan, atau hierarki) dan mengidentifikasi bagian dengan sedikit interaktivitas atau tanpa reaktivitas. Untuk setiap bagian yang sebagian besar statis ini, kode JavaScript yang sesuai kemudian diubah menjadi referensi inert dan fitur dekoratif, sehingga mengurangi jejak sisi kliennya menjadi hampir nol.
Pendekatan rehidrasi parsial memiliki masalah dan komprominya sendiri. Hal ini menimbulkan beberapa tantangan menarik untuk penyimpanan ke dalam cache, dan navigasi sisi klien berarti kita tidak dapat berasumsi bahwa HTML yang dirender server untuk bagian aplikasi yang inert tersedia tanpa pemuatan halaman penuh.
Rendering trisomorfik
Jika service worker adalah opsi untuk Anda, pertimbangkan rendering trisomorfik. Teknik ini memungkinkan Anda menggunakan rendering sisi server streaming untuk navigasi awal atau non-JavaScript, lalu meminta pekerja layanan Anda melakukan rendering HTML untuk navigasi setelah diinstal. Hal ini dapat membuat komponen dan template yang di-cache tetap terbaru dan mengaktifkan navigasi bergaya SPA untuk merender tampilan baru dalam sesi yang sama. Pendekatan ini berfungsi optimal jika Anda dapat membagikan kode template dan perutean yang sama antara server, halaman klien, dan pekerja layanan.
Pertimbangan SEO
Saat memilih strategi rendering web, tim sering kali mempertimbangkan dampak SEO. Rendering sisi server adalah pilihan populer untuk memberikan pengalaman "tampilan lengkap" yang dapat ditafsirkan oleh crawler. Crawler dapat memahami JavaScript, tetapi sering kali ada batasan terkait cara crawler merender. Rendering sisi klien dapat berfungsi, tetapi sering kali memerlukan pengujian dan overhead tambahan. Baru-baru ini, rendering dinamis juga menjadi opsi yang layak dipertimbangkan jika arsitektur Anda sangat bergantung pada JavaScript sisi klien.
Kesimpulan
Saat memutuskan pendekatan untuk rendering, ukur dan pahami bottleneck Anda. Pertimbangkan apakah rendering statis atau rendering sisi server dapat membantu Anda mencapai sebagian besar tujuan. Tidak masalah jika Anda mengirimkan sebagian besar HTML dengan JavaScript minimal untuk mendapatkan pengalaman interaktif. Berikut adalah infografis praktis yang menunjukkan spektrum server-klien:
Kredit
Terima kasih kepada semua orang atas ulasan dan inspirasi mereka:
Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson, dan Sebastian Markbåge.