Merender HTML dengan JavaScript berbeda dengan merender HTML yang dikirim oleh server—dan yang dapat memengaruhi performa. Pelajari perbedaan dalam panduan ini, dan tindakan yang dapat Anda lakukan untuk mempertahankan performa rendering situs—terutama saat berinteraksi.
Penguraian dan perenderan HTML adalah sesuatu yang dilakukan browser dengan sangat baik secara default untuk situs web yang menggunakan logika navigasi bawaan browser—terkadang disebut "pemuatan halaman tradisional" atau "navigasi yang sulit". Situs web semacam ini terkadang disebut aplikasi multi-halaman (MPA).
Namun, developer dapat menyesuaikan setelan default browser agar sesuai dengan kebutuhan aplikasi mereka. Hal ini tentu saja terjadi untuk situs yang menggunakan pola aplikasi web satu halaman (SPA), yang secara dinamis membuat bagian besar HTML/DOM pada 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 penggunaan HTML yang dikirim oleh server ke browser dibandingkan dengan membuatnya pada klien dengan JavaScript, dan bagaimana HTML dapat menghasilkan latensi interaksi yang tinggi pada momen penting.
Cara browser merender HTML yang disediakan oleh server
Pola navigasi yang digunakan dalam pemuatan halaman biasa melibatkan penerimaan HTML dari server di setiap navigasi. Jika Anda memasukkan URL di kolom URL browser atau mengklik link di MPA, rangkaian peristiwa berikut akan terjadi:
- Browser akan mengirimkan permintaan navigasi untuk URL yang disediakan.
- Server merespons dengan HTML dalam potongan.
Langkah terakhir ini adalah kuncinya. Cloud Bigtable juga merupakan salah satu pengoptimalan performa paling mendasar dalam pertukaran server/browser dan dikenal sebagai streaming. Jika server dapat mulai mengirimkan HTML sesegera mungkin, dan browser tidak menunggu seluruh respons diterima, maka browser dapat memproses HTML dalam potongan setelah diterima.
![Screenshot penguraian HTML yang dikirim oleh server divisualisasikan di panel performa Chrome DevTools. Saat HTML di-streaming, potongannya diproses di beberapa tugas yang lebih pendek, dan rendering dilakukan secara bertahap.](https://web.dev/static/articles/client-side-rendering-of-html-and-interactivity/image/a-screenshot-parsing-ht-f2443fe1b1888.png?authuser=19&hl=id)
Seperti kebanyakan hal yang terjadi di browser, penguraian HTML terjadi di dalam tugas. Ketika HTML di-streaming dari server ke browser, browser mengoptimalkan penguraian HTML tersebut dengan melakukannya sedikit demi sedikit seiring bit dari aliran data tersebut masuk dalam potongan. Konsekuensinya adalah browser menghasilkan thread utama secara berkala setelah memproses setiap potongan, yang menghindari tugas yang panjang. Artinya, pekerjaan lain dapat terjadi saat HTML sedang diuraikan, termasuk tugas rendering inkremental yang diperlukan untuk menampilkan halaman kepada pengguna, serta pemrosesan interaksi pengguna yang mungkin terjadi selama periode pengaktifan halaman yang penting. Pendekatan ini diterjemahkan ke skor Interaction to Next Paint (INP) yang lebih baik untuk halaman.
Kesimpulannya? Saat melakukan streaming HTML dari server, Anda mendapatkan penguraian dan rendering HTML inkremental serta menghasilkan thread utama secara gratis 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 akan disediakan oleh server, beberapa situs akan menggunakan pola SPA. Pendekatan ini sering melibatkan muatan awal HTML minimal yang disediakan oleh server, tetapi kemudian klien akan mengisi area konten utama laman dengan HTML yang disusun dari data yang diambil dari server. Navigasi berikutnya—terkadang disebut sebagai "navigasi ringan" dalam hal ini—ditangani sepenuhnya oleh JavaScript untuk mengisi halaman dengan HTML baru.
Perenderan sisi klien juga dapat terjadi di non-SPA dalam kasus yang lebih terbatas, yaitu HTML ditambahkan secara dinamis ke DOM melalui JavaScript.
Ada beberapa cara umum untuk membuat HTML atau menambahkan ke DOM melalui JavaScript:
- Properti
innerHTML
memungkinkan Anda menetapkan konten pada elemen yang ada melalui string, yang akan diurai browser ke dalam DOM. - Metode
document.createElement
memungkinkan Anda membuat elemen baru untuk ditambahkan ke DOM tanpa menggunakan penguraian HTML browser apa pun. - Metode
document.write
memungkinkan Anda menulis HTML ke dokumen (dan browser akan mengurainya, seperti dalam pendekatan #1). Namun, karena sejumlah alasan, penggunaandocument.write
sangat tidak disarankan.
![Screenshot penguraian HTML yang dirender melalui JavaScript yang divisualisasikan di panel performa Chrome DevTools. Pekerjaan terjadi dalam satu tugas panjang yang memblokir thread utama.](https://web.dev/static/articles/client-side-rendering-of-html-and-interactivity/image/a-screenshot-parsing-ht-7b89c1ab03511.png?authuser=19&hl=id)
Konsekuensi dari pembuatan HTML/DOM melalui JavaScript sisi klien dapat sangat signifikan:
- Tidak seperti HTML yang di-streaming oleh server sebagai respons terhadap permintaan navigasi, tugas JavaScript pada klien tidak secara otomatis dipisah, sehingga dapat menghasilkan tugas panjang yang memblokir thread utama. Artinya, INP halaman Anda dapat terkena dampak negatif jika Anda membuat terlalu banyak HTML/DOM pada 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) suatu halaman. Meskipun ini bukan masalah performa runtime (tetapi ini masalah penundaan jaringan dalam mengambil resource yang penting), Anda tidak ingin LCP situs Anda terpengaruh oleh tindakan pengoptimalan performa browser dasar ini.
Yang dapat Anda lakukan terkait dampak performa dari rendering sisi klien
Jika situs Anda sangat bergantung pada rendering sisi klien dan Anda telah mengamati nilai INP yang buruk pada data kolom, Anda mungkin bertanya-tanya apakah rendering sisi klien ada hubungannya dengan masalah tersebut. Misalnya, jika situs Anda adalah SPA, data kolom dapat mengungkapkan interaksi yang bertanggung jawab atas pekerjaan rendering yang cukup besar.
Apa pun penyebabnya, berikut beberapa penyebab potensial yang dapat Anda pelajari untuk membantu memperbaiki segala sesuatunya.
Berikan HTML sebanyak mungkin dari server
Seperti yang disebutkan sebelumnya, browser menangani HTML dari server dengan cara yang sangat berperforma baik secara default. Ini akan memecah penguraian dan perenderan HTML dengan cara yang menghindari tugas yang berjalan lama, dan mengoptimalkan jumlah total waktu thread utama. Hal ini menyebabkan Total Blocking Time (TBT) yang lebih rendah, dan TBT sangat berkorelasi dengan INP.
Anda mungkin mengandalkan framework frontend untuk membangun situs Anda. Jika ya, pastikan 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, Anda harus memanfaatkan Server DOM API untuk merender HTML di server. Namun, perlu diketahui: metode tradisional rendering sisi server menggunakan pendekatan sinkron, yang dapat menyebabkan Time to First Byte (TTFB) 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 agar server dapat memulai streaming HTML ke browser sesegera mungkin. Next.js—framework berbasis React—menyediakan banyak praktik terbaik secara default. Selain merender HTML secara otomatis pada server, hal ini juga dapat menghasilkan 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 khusus browser (misalnya,
window
), Anda mungkin tidak dapat merender HTML komponen tersebut di server. Pelajari pendekatan alternatif jika memungkinkan sehingga Anda tidak menyebabkan rendering sisi klien yang tidak perlu. SvelteKit—yaitu untuk Svelte karena Next.js adalah untuk React—menyematkan banyak praktik terbaik ke dalam project Svelte Anda, sehingga Anda dapat menghindari potensi kesalahan dalam project yang menggunakan Svelte saja.
Membatasi jumlah node DOM yang dibuat di klien
Jika DOM berukuran besar, pemrosesan yang diperlukan untuk merendernya cenderung meningkat. Baik situs Anda merupakan SPA yang lengkap, atau memasukkan node baru ke dalam DOM yang ada sebagai hasil dari interaksi untuk MPA, pertimbangkan untuk mempertahankan DOM tersebut sekecil mungkin. Hal ini akan membantu mengurangi pekerjaan yang diperlukan selama rendering sisi klien untuk menampilkan HTML tersebut, yang diharapkan dapat membantu menjaga INP situs Anda tetap rendah.
Pertimbangkan arsitektur pekerja layanan streaming
Ini adalah teknik tingkat lanjut, yang mungkin tidak berfungsi dengan mudah di setiap kasus penggunaan, tetapi ini adalah teknik yang dapat mengubah MPA Anda menjadi situs yang terasa seperti dimuat secara instan saat pengguna menavigasi dari satu halaman ke halaman berikutnya. Anda dapat menggunakan pekerja layanan untuk melakukan precache bagian statis situs Anda di CacheStorage
saat menggunakan ReadableStream
API untuk mengambil HTML halaman lainnya dari server.
Bila Anda berhasil menggunakan teknik ini, Anda tidak membuat HTML pada klien, tetapi pemuatan instan sebagian 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 dari rendering sisi klien. Tindakan ini juga mengurangi jumlah HTML yang Anda minta dari server.
Singkatnya, arsitektur pekerja layanan streaming tidak menggantikan logika navigasi bawaan browser, melainkan ditambahkan ke dalamnya. 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 memengaruhi performa. Jika Anda mengandalkan server untuk mengirim semua (atau sebagian besar) HTML yang diperlukan agar situs Anda berfungsi, Anda akan mendapatkan banyak hal gratis: penguraian dan rendering inkremental, dan hasil otomatis ke thread utama untuk menghindari tugas yang lama.
Perenderan HTML sisi klien memperkenalkan sejumlah potensi masalah kinerja yang dapat dihindari dalam banyak kasus. Namun, sehubungan dengan persyaratan masing-masing situs, hal ini tidak sepenuhnya dapat dihindari 100% setiap saat. Untuk mengurangi potensi tugas panjang yang dapat diakibatkan oleh rendering situs klien yang berlebihan, pastikan Anda mengirim sebanyak mungkin HTML situs web Anda dari server jika memungkinkan, pertahankan ukuran DOM sekecil mungkin untuk HTML yang harus dirender pada klien, dan pertimbangkan arsitektur alternatif untuk mempercepat pengiriman HTML ke klien sekaligus memanfaatkan penguraian inkremental dan rendering yang disediakan browser untuk HTML yang dimuat dari server.
Jika Anda dapat membuat rendering sisi klien seminimal mungkin, Anda tidak hanya akan meningkatkan INP situs, tetapi juga metrik lainnya seperti LCP, TBT, dan bahkan mungkin TTFB Anda dalam beberapa kasus.
Banner besar dari Unsplash, oleh Maik Jonietz.