Rendering sisi klien untuk HTML dan interaktivitas

Merender HTML dengan JavaScript berbeda dengan merender HTML yang dikirim oleh server—dan hal ini dapat memengaruhi performa. Pelajari perbedaannya dalam panduan ini, dan tindakan yang dapat Anda lakukan untuk mempertahankan performa rendering situs—terutama terkait interaksi.

Pemrosesan dan rendering HTML adalah sesuatu yang dilakukan browser dengan sangat baik secara default untuk situs yang menggunakan logika navigasi bawaan browser—terkadang disebut "pemuatan halaman tradisional" atau "navigasi keras". Situs tersebut terkadang disebut aplikasi multi-halaman (MPA).

Namun, developer dapat mengatasi setelan default browser agar sesuai dengan kebutuhan aplikasi mereka. Hal ini tentu berlaku untuk situs yang menggunakan pola aplikasi web satu halaman (SPA), yang secara dinamis membuat sebagian besar HTML/DOM di klien dengan JavaScript. Rendering sisi klien adalah nama untuk pola desain ini, dan dapat memengaruhi Interaction to Next Paint (INP) situs Anda jika pekerjaan yang terlibat berlebihan.

Panduan ini akan membantu Anda mempertimbangkan perbedaan antara menggunakan HTML yang dikirim oleh server ke browser versus membuatnya di klien dengan JavaScript, dan bagaimana hal ini dapat menyebabkan latensi interaksi yang tinggi pada saat-saat penting.

Cara browser merender HTML yang disediakan oleh server

Pola navigasi yang digunakan dalam pemuatan halaman tradisional melibatkan penerimaan HTML dari server pada setiap navigasi. Jika Anda memasukkan URL di kolom URL browser atau mengklik link di MPA, rangkaian peristiwa berikut akan terjadi:

  1. Browser mengirimkan permintaan navigasi untuk URL yang diberikan.
  2. Server merespons dengan HTML dalam beberapa bagian.

Langkah terakhir ini adalah kuncinya. Ini juga merupakan salah satu pengoptimalan performa paling mendasar dalam pertukaran server/browser, dan dikenal sebagai streaming. Jika server dapat mulai mengirim HTML sesegera mungkin, dan browser tidak menunggu seluruh respons tiba, browser dapat memproses HTML dalam beberapa bagian saat tiba.

Screenshot penguraian HTML yang dikirim oleh server yang divisualisasikan di panel performa Chrome DevTools. Saat HTML di-streaming, potongannya diproses di beberapa tugas yang lebih singkat, dan rendering bersifat inkremental.
Pemrosesan dan rendering HTML yang disediakan oleh server seperti yang divisualisasi di panel performa Chrome DevTools. Tugas yang terlibat dalam mengurai HTML dan merendernya dibagi menjadi beberapa bagian.

Seperti kebanyakan hal yang terjadi di browser, penguraian HTML terjadi dalam tugas. Saat HTML di-streaming dari server ke browser, browser akan mengoptimalkan penguraian HTML tersebut dengan melakukannya sedikit demi sedikit saat bit streaming tersebut tiba dalam beberapa bagian. Konsekuensinya adalah browser akan beralih ke thread utama secara berkala setelah memproses setiap bagian, sehingga menghindari tugas yang lama. Artinya, pekerjaan lain dapat terjadi saat HTML sedang diuraikan, termasuk pekerjaan rendering inkremental yang diperlukan untuk menampilkan halaman kepada pengguna, serta memproses interaksi pengguna yang mungkin terjadi selama periode pengaktifan halaman yang penting. Pendekatan ini menghasilkan skor Interaction to Next Paint (INP) yang lebih baik untuk halaman.

Apa yang bisa diambil dari hal ini? Saat melakukan streaming HTML dari server, Anda mendapatkan penguraian dan rendering HTML inkremental serta pemberian otomatis ke thread utama secara gratis. Anda tidak mendapatkannya dengan rendering sisi klien.

Cara browser merender HTML yang disediakan oleh JavaScript

Meskipun setiap permintaan navigasi ke halaman memerlukan sejumlah HTML yang disediakan oleh server, beberapa situs akan menggunakan pola SPA. Pendekatan ini sering kali melibatkan payload awal HTML minimal yang disediakan oleh server, tetapi kemudian klien akan mengisi area konten utama halaman dengan HTML yang disusun dari data yang diambil dari server. Navigasi berikutnya—terkadang disebut sebagai "navigasi soft" dalam hal ini—ditangani sepenuhnya oleh JavaScript untuk mengisi halaman dengan HTML baru.

Rendering sisi klien juga dapat terjadi di non-SPA dalam kasus yang lebih terbatas, yaitu saat HTML ditambahkan secara dinamis ke DOM melalui JavaScript.

Ada beberapa cara umum untuk membuat HTML atau menambahkan ke DOM melalui JavaScript:

  1. Properti innerHTML memungkinkan Anda menetapkan konten pada elemen yang ada melalui string, yang diuraikan browser ke dalam DOM.
  2. Metode document.createElement memungkinkan Anda membuat elemen baru untuk ditambahkan ke DOM tanpa menggunakan penguraian HTML browser.
  3. Metode document.write memungkinkan Anda menulis HTML ke dokumen (dan browser mengurainya, seperti dalam pendekatan #1). Namun, karena beberapa alasan, penggunaan document.write sangat tidak dianjurkan.
Screenshot penguraian HTML yang dirender melalui JavaScript yang divisualisasikan di panel performa Chrome DevTools. Pekerjaan terjadi dalam satu tugas panjang yang memblokir thread utama.
Pemrosesan dan rendering HTML melalui JavaScript di klien seperti yang divisualisasi di panel performa Chrome DevTools. Tugas yang terlibat dalam penguraian dan rendering tidak dikelompokkan, sehingga menghasilkan tugas yang lama dan memblokir thread utama.

Konsekuensi membuat HTML/DOM melalui JavaScript sisi klien dapat menjadi signifikan:

  • Tidak seperti HTML yang di-streaming oleh server sebagai respons terhadap permintaan navigasi, tugas JavaScript di klien tidak otomatis dikelompokkan, yang dapat menyebabkan tugas panjang yang memblokir thread utama. Artinya, INP halaman Anda dapat terpengaruh secara negatif jika Anda membuat terlalu banyak HTML/DOM dalam satu waktu di klien.
  • Jika HTML dibuat di klien selama startup, resource yang dirujuk di dalamnya tidak akan ditemukan oleh pemindai pramuat browser. Hal ini tentu akan berdampak negatif pada Largest Contentful Paint (LCP) halaman. Meskipun ini bukan masalah performa runtime (sebaliknya, ini adalah masalah penundaan jaringan dalam mengambil resource penting), Anda tidak ingin LCP situs terpengaruh dengan mengabaikan pengoptimalan performa browser yang mendasar ini.

Yang dapat Anda lakukan terkait dampak performa rendering sisi klien

Jika situs Anda sangat bergantung pada rendering sisi klien dan Anda mengamati nilai INP yang buruk dalam data kolom, Anda mungkin bertanya-tanya apakah rendering sisi klien terkait dengan masalah tersebut. Misalnya, jika situs Anda adalah SPA, data kolom Anda dapat mengungkapkan interaksi yang bertanggung jawab atas pekerjaan rendering yang cukup besar.

Apa pun penyebabnya, berikut beberapa kemungkinan penyebab yang dapat Anda pelajari untuk membantu mengatasi masalah ini.

Berikan HTML sebanyak mungkin dari server

Seperti yang disebutkan sebelumnya, browser menangani HTML dari server dengan cara yang sangat berperforma tinggi secara default. Hal ini akan memecah penguraian dan rendering HTML dengan cara yang menghindari tugas yang lama, dan mengoptimalkan jumlah total waktu thread utama. Hal ini menyebabkan Total Waktu Pemblokiran (TBT) yang lebih rendah, dan TBT sangat berkorelasi dengan INP.

Anda mungkin mengandalkan framework frontend untuk membuat situs. Jika demikian, Anda harus memastikan bahwa Anda merender HTML komponen di server. Hal ini akan membatasi jumlah rendering sisi klien awal yang diperlukan situs Anda, dan akan menghasilkan pengalaman yang lebih baik.

  • Untuk React, sebaiknya gunakan Server DOM API untuk merender HTML di server. Namun, perhatikan: metode rendering sisi server tradisional menggunakan pendekatan sinkron, yang dapat menyebabkan Waktu ke Byte Pertama (TTFB) yang lebih lama, serta metrik berikutnya seperti First Contentful Paint (FCP) dan LCP. Jika memungkinkan, pastikan Anda menggunakan API streaming untuk Node.js atau runtime JavaScript lainnya sehingga server dapat mulai melakukan streaming HTML ke browser sesegera mungkin. Next.js—framework berbasis React—menyediakan banyak praktik terbaik secara default. Selain merender HTML secara otomatis di server, server ini juga dapat membuat HTML secara statis untuk halaman yang tidak berubah berdasarkan konteks pengguna (seperti autentikasi).
  • Vue juga melakukan rendering sisi klien secara default. Namun, seperti React, Vue juga dapat merender HTML komponen Anda di server. Manfaatkan API sisi server ini jika memungkinkan, atau pertimbangkan abstraksi tingkat yang lebih tinggi untuk project Vue Anda agar praktik terbaik lebih mudah diterapkan.
  • Svelte merender HTML di server secara default—meskipun jika kode komponen Anda memerlukan akses ke namespace eksklusif browser (misalnya, window), Anda mungkin tidak dapat merender HTML komponen tersebut di server. Pelajari pendekatan alternatif jika memungkinkan agar Anda tidak menyebabkan rendering sisi klien yang tidak perlu. SvelteKit—yang merupakan Svelte untuk React—menyisipkan banyak praktik terbaik ke dalam project Svelte Anda, sehingga Anda dapat menghindari potensi masalah dalam project yang hanya menggunakan Svelte.

Membatasi jumlah node DOM yang dibuat di klien

Jika DOM besar, pemrosesan yang diperlukan untuk merendernya cenderung meningkat. Baik situs Anda adalah SPA yang lengkap, atau memasukkan node baru ke DOM yang ada sebagai hasil interaksi untuk MPA, sebaiknya pertahankan DOM tersebut sekecil mungkin. Tindakan ini akan membantu mengurangi pekerjaan yang diperlukan selama rendering sisi klien untuk menampilkan HTML tersebut, sehingga diharapkan dapat membantu menjaga INP situs Anda tetap lebih rendah.

Pertimbangkan arsitektur pekerja layanan streaming

Ini adalah teknik lanjutan—yang mungkin tidak mudah digunakan dengan setiap kasus penggunaan—tetapi teknik ini dapat mengubah MPA Anda menjadi situs yang terasa dimuat secara instan saat pengguna membuka halaman berikutnya. Anda dapat menggunakan pekerja layanan untuk melakukan pra-cache bagian statis situs di CacheStorage saat menggunakan ReadableStream API untuk mengambil sisa HTML halaman dari server.

Jika berhasil menggunakan teknik ini, Anda tidak membuat HTML di klien, tetapi pemuatan instan parsial konten dari cache akan memberikan kesan bahwa situs Anda dimuat dengan cepat. Situs yang menggunakan pendekatan ini dapat terasa hampir seperti SPA, tetapi tanpa kelemahan rendering sisi klien. Hal ini juga mengurangi jumlah HTML yang Anda minta dari server.

Singkatnya, arsitektur pekerja layanan streaming tidak mengganti logika navigasi bawaan browser, tetapi menambahkannya. Untuk mengetahui informasi selengkapnya tentang cara melakukannya dengan Workbox, baca Aplikasi multihalaman yang lebih cepat dengan streaming.

Kesimpulan

Cara situs Anda menerima dan merender HTML akan memengaruhi performa. Jika mengandalkan server untuk mengirim semua (atau sebagian besar) HTML yang diperlukan agar situs berfungsi, Anda akan mendapatkan banyak hal secara gratis: penguraian dan rendering inkremental, serta pemberian otomatis ke thread utama untuk menghindari tugas yang lama.

Rendering HTML sisi klien menyebabkan sejumlah potensi masalah performa yang dapat dihindari dalam banyak kasus. Namun, karena persyaratan setiap situs, hal ini tidak sepenuhnya dapat dihindari 100%. Untuk mengurangi potensi tugas yang lama yang dapat dihasilkan dari rendering situs klien yang berlebihan, pastikan Anda mengirim HTML situs sebanyak mungkin dari server jika memungkinkan, pertahankan ukuran DOM Anda sekecil mungkin untuk HTML yang harus dirender di klien, dan pertimbangkan arsitektur alternatif untuk mempercepat pengiriman HTML ke klien sekaligus memanfaatkan penguraian dan rendering inkremental yang disediakan browser untuk HTML yang dimuat dari server.

Jika Anda dapat membuat rendering sisi klien situs Anda seminimal mungkin, Anda tidak hanya akan meningkatkan INP situs, tetapi juga metrik lainnya seperti LCP, TBT, dan mungkin bahkan TTFB dalam beberapa kasus.

Banner besar dari Unsplash, oleh Maik Jonietz.