Mengoptimalkan penundaan input

Cari tahu apa itu penundaan input, dan pelajari teknik untuk menguranginya agar interaktivitas lebih cepat.

Interaksi di web adalah hal yang rumit, dengan berbagai aktivitas yang terjadi di browser untuk mendorongnya. Namun, semuanya memiliki kesamaan, yaitu menimbulkan beberapa penundaan input sebelum callback peristiwa mulai berjalan. Dalam panduan ini, Anda akan mempelajari apa itu penundaan input, dan apa yang dapat Anda lakukan untuk meminimalkannya agar interaksi situs Anda berjalan lebih cepat.

Apa yang dimaksud dengan penundaan input?

Penundaan input adalah jangka waktu yang dimulai dari saat pengguna pertama kali berinteraksi dengan halaman—seperti mengetuk layar, mengklik dengan mouse, atau menekan tombol—hingga saat callback peristiwa untuk interaksi mulai berjalan. Setiap interaksi dimulai dengan sejumlah keterlambatan input.

Visualisasi sederhana dari keterlambatan input. Di sebelah kiri, ada gambar garis kursor mouse dengan kilauan bintang di belakangnya, yang menandakan awal interaksi. Di sebelah kanan adalah gambar garis roda gigi, yang menandakan kapan pengendali peristiwa untuk interaksi mulai berjalan. Ruang di antaranya ditandai sebagai penundaan input dengan tanda kurung kurawal.
Mekanisme di balik penundaan input. Saat input diterima oleh sistem operasi, input tersebut harus diteruskan ke browser sebelum interaksi dimulai. Proses ini memerlukan waktu tertentu, dan dapat ditingkatkan dengan tugas thread utama yang ada.

Sebagian penundaan input tidak dapat dihindari: sistem operasi selalu memerlukan waktu untuk mengenali peristiwa input dan meneruskannya ke browser. Namun, bagian penundaan input tersebut sering kali bahkan tidak terlihat, dan ada hal lain yang terjadi di halaman itu sendiri yang dapat membuat penundaan input cukup lama sehingga menyebabkan masalah.

Cara memikirkan penundaan input

Secara umum, Anda harus membuat setiap bagian interaksi sesingkat mungkin agar situs Anda memiliki peluang terbaik untuk memenuhi nilai minimum "baik" metrik Interaction to Next Paint (INP), apa pun perangkat pengguna. Menjaga penundaan input tetap terkendali hanyalah salah satu bagian dari memenuhi nilai minimum tersebut.

Oleh karena itu, Anda harus menargetkan penundaan input sesingkat mungkin untuk memenuhi nilai minimum "baik" INP. Namun, perlu diketahui bahwa Anda tidak dapat menghilangkan penundaan input sepenuhnya. Selama Anda menghindari pekerjaan thread utama yang berlebihan saat pengguna mencoba berinteraksi dengan halaman Anda, penundaan input Anda akan cukup rendah untuk menghindari masalah.

Cara meminimalkan penundaan input

Seperti yang telah disebutkan sebelumnya, beberapa keterlambatan input tidak dapat dihindari, tetapi di sisi lain, beberapa keterlambatan input dapat dihindari. Berikut beberapa hal yang perlu dipertimbangkan jika Anda mengalami penundaan input yang lama.

Menghindari timer berulang yang memulai pekerjaan thread utama yang berlebihan

Ada dua fungsi timer yang umum digunakan di JavaScript yang dapat menyebabkan keterlambatan input: setTimeout dan setInterval. Perbedaan antara keduanya adalah setTimeout menjadwalkan callback untuk dijalankan setelah waktu yang ditentukan. Di sisi lain, setInterval menjadwalkan callback untuk berjalan setiap n milidetik selamanya, atau hingga timer dihentikan dengan clearInterval.

setTimeout tidak bermasalah—bahkan, dapat membantu menghindari tugas berdurasi lama. Namun, hal ini bergantung pada kapan waktu tunggu habis terjadi, dan apakah pengguna mencoba berinteraksi dengan halaman saat callback waktu tunggu habis berjalan.

Selain itu, setTimeout dapat dijalankan dalam loop atau secara berulang, yang bertindak lebih seperti setInterval, meskipun sebaiknya tidak menjadwalkan iterasi berikutnya hingga iterasi sebelumnya selesai. Meskipun ini berarti loop akan menghasilkan thread utama setiap kali setTimeout dipanggil, Anda harus berhati-hati untuk memastikan callback-nya tidak melakukan pekerjaan yang berlebihan.

setInterval menjalankan callback pada interval, sehingga jauh lebih mungkin mengganggu interaksi. Hal ini karena—tidak seperti satu instance panggilan setTimeout, yang merupakan callback satu kali yang mungkin menghalangi interaksi pengguna—sifat setInterval yang berulang membuatnya jauh lebih mungkin akan menghalangi interaksi, sehingga meningkatkan penundaan input interaksi.

Screenshot profiler performa di Chrome DevTools yang menunjukkan penundaan input. Tugas yang diaktifkan oleh fungsi timer terjadi tepat sebelum pengguna memulai interaksi klik. Namun, timer memperpanjang penundaan input, sehingga menyebabkan callback peristiwa interaksi berjalan lebih lambat daripada yang seharusnya.
Timer yang didaftarkan oleh panggilan setInterval sebelumnya yang berkontribusi pada penundaan input seperti yang digambarkan di panel performa Chrome DevTools. Penundaan input yang ditambahkan menyebabkan callback peristiwa untuk interaksi berjalan lebih lambat daripada yang seharusnya.

Jika timer terjadi dalam kode pihak pertama, Anda memiliki kontrol atas timer tersebut. Evaluasi apakah Anda membutuhkannya, atau lakukan yang terbaik untuk mengurangi pekerjaan di dalamnya sebanyak mungkin. Namun, timer dalam skrip pihak ketiga berbeda. Anda sering kali tidak memiliki kontrol atas apa yang dilakukan skrip pihak ketiga, dan memperbaiki masalah performa dalam kode pihak ketiga sering kali melibatkan kerja sama dengan pemangku kepentingan untuk menentukan apakah skrip pihak ketiga tertentu diperlukan, dan jika demikian, hubungi vendor skrip pihak ketiga untuk menentukan apa yang dapat dilakukan untuk memperbaiki masalah performa yang mungkin disebabkan oleh skrip tersebut di situs Anda.

Menghindari tugas berdurasi lama

Salah satu cara untuk mengurangi penundaan input yang lama adalah dengan menghindari tugas berdurasi lama. Jika Anda memiliki pekerjaan thread utama yang berlebihan dan memblokir thread utama selama interaksi, hal ini akan menambah penundaan input untuk interaksi tersebut sebelum tugas berdurasi lama sempat selesai.

Visualisasi tentang seberapa lama tugas memperpanjang penundaan input. Di bagian atas, interaksi terjadi segera setelah satu tugas berdurasi lama berjalan, sehingga menyebabkan penundaan input yang signifikan yang menyebabkan callback peristiwa berjalan jauh lebih lambat daripada yang seharusnya. Di bagian bawah, interaksi terjadi pada waktu yang hampir bersamaan, tetapi tugas berdurasi lama dipecah menjadi beberapa tugas yang lebih kecil dengan menghasilkan, sehingga callback peristiwa interaksi dapat berjalan jauh lebih cepat.
Visualisasi tentang apa yang terjadi pada interaksi saat tugas terlalu panjang dan browser tidak dapat merespons interaksi dengan cukup cepat, dibandingkan saat tugas yang lebih panjang dipecah menjadi tugas yang lebih kecil.

Selain meminimalkan jumlah pekerjaan yang Anda lakukan dalam tugas—dan Anda harus selalu berusaha melakukan pekerjaan sesedikit mungkin di thread utama—Anda dapat meningkatkan responsivitas terhadap input pengguna dengan memecah tugas berdurasi lama.

Perhatikan tumpang-tindih interaksi

Bagian yang sangat menantang dalam mengoptimalkan INP adalah jika Anda memiliki interaksi yang tumpang-tindih. Tumpang-tindih interaksi berarti setelah berinteraksi dengan satu elemen, Anda melakukan interaksi lain dengan halaman sebelum interaksi awal sempat merender frame berikutnya.

Penggambaran kapan tugas dapat tumpang-tindih sehingga menghasilkan penundaan input yang lama. Dalam penggambaran ini, interaksi klik tumpang-tindih dengan interaksi keydown untuk meningkatkan penundaan input untuk interaksi keydown.
Visualisasi dua interaksi serentak di profiler performa di DevTools Chrome. Pekerjaan rendering dalam interaksi klik awal menyebabkan penundaan input untuk interaksi keyboard berikutnya.

Sumber tumpang-tindih interaksi mungkin sesederhana pengguna melakukan banyak interaksi dalam waktu singkat. Hal ini dapat terjadi saat pengguna mengetik di kolom formulir, tempat banyak interaksi keyboard dapat terjadi dalam jangka waktu yang sangat singkat. Jika pekerjaan pada peristiwa utama sangat mahal—seperti dalam kasus umum kolom pelengkapan otomatis tempat permintaan jaringan dibuat ke back-end—Anda memiliki beberapa opsi:

  • Pertimbangkan untuk melakukan debounce pada input untuk membatasi frekuensi callback peristiwa dieksekusi dalam jangka waktu tertentu.
  • Gunakan AbortController untuk membatalkan permintaan fetch keluar agar thread utama tidak macet saat menangani callback fetch. Catatan: properti signal instance AbortController juga dapat digunakan untuk membatalkan peristiwa.

Sumber lain dari peningkatan penundaan input karena interaksi yang tumpang-tindih dapat berupa animasi yang mahal. Secara khusus, animasi di JavaScript dapat memicu banyak panggilan requestAnimationFrame, yang dapat mengganggu interaksi pengguna. Untuk mengatasinya, gunakan animasi CSS jika memungkinkan untuk menghindari antrean frame animasi yang berpotensi mahal—tetapi jika Anda melakukannya, pastikan Anda menghindari animasi non-komposit sehingga animasi berjalan terutama di thread GPU dan compositor, bukan di thread utama.

Kesimpulan

Meskipun penundaan input mungkin tidak mewakili sebagian besar waktu yang diperlukan interaksi untuk berjalan, penting untuk dipahami bahwa setiap bagian interaksi memerlukan waktu yang dapat Anda kurangi. Jika Anda mengamati penundaan input yang lama, Anda memiliki peluang untuk menguranginya. Menghindari callback timer berulang, memecah tugas berdurasi lama, dan menyadari potensi tumpang-tindih interaksi dapat membantu Anda mengurangi penundaan input, sehingga menghasilkan interaktivitas yang lebih cepat bagi pengguna situs Anda.