Mengoptimalkan penundaan input

Cari tahu apa yang dimaksud dengan 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, kesamaan dari semua interaksi tersebut adalah bahwa interaksi tersebut mengalami penundaan input sebelum callback peristiwanya mulai berjalan. Dalam panduan ini, Anda akan mempelajari apa yang dimaksud dengan penundaan input, dan apa yang dapat Anda lakukan untuk meminimalkannya sehingga interaksi situs Anda berjalan lebih cepat.

Apa yang dimaksud dengan penundaan input?

Penundaan input adalah jangka waktu yang dimulai 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 penundaan input.

Visualisasi sederhana penundaan input. Di sebelah kiri, ada gambar garis kursor mouse dengan starburst 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 dicatat sebagai penundaan input dengan kurung kurawal.
Mekanisme di balik penundaan input. Saat input diterima oleh sistem operasi, input tersebut harus diteruskan ke browser sebelum interaksi dimulai. Hal ini memerlukan waktu tertentu, dan dapat ditingkatkan dengan pekerjaan thread utama yang ada.

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

Cara mempertimbangkan penundaan input

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

Oleh karena itu, Anda harus mengupayakan penundaan input sesingkat mungkin untuk memenuhi nilai minimum "baik" INP. Namun, Anda harus mengetahui 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 dikatakan sebelumnya, beberapa penundaan input tidak dapat dihindari, tetapi di sisi lain, beberapa penundaan input dapat dihindari. Berikut beberapa hal yang perlu dipertimbangkan jika Anda mengalami penundaan input yang lama.

Hindari timer berulang yang memicu pekerjaan thread utama yang berlebihan

Ada dua fungsi timer yang umum digunakan di JavaScript yang dapat berkontribusi pada penundaan input: setTimeout dan setInterval. Perbedaan antara keduanya adalah setTimeout menjadwalkan callback untuk dijalankan setelah waktu yang ditentukan. setInterval, di sisi lain, menjadwalkan callback untuk dijalankan setiap n milidetik secara terus-menerus, atau hingga timer dihentikan dengan clearInterval.

setTimeout tidak bermasalah dengan sendirinya—bahkan, fungsi ini dapat membantu dalam menghindari tugas yang panjang. Namun, hal ini bergantung pada kapan waktu tunggu terjadi, dan apakah pengguna mencoba berinteraksi dengan halaman saat callback waktu tunggu berjalan.

Selain itu, setTimeout dapat dijalankan dalam loop atau secara rekursif, yang bertindak lebih seperti setInterval, meskipun sebaiknya tidak menjadwalkan iterasi berikutnya hingga iterasi sebelumnya selesai. Meskipun hal 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, dan oleh karena itu, kemungkinan besar akan menghambat interaksi. Hal ini karena—tidak seperti satu instance panggilan setTimeout, yang merupakan callback satu kali yang mungkin menghambat interaksi pengguna—sifat berulang setInterval membuatnya lebih mungkin menghambat 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 callback peristiwa interaksi berjalan lebih lambat dari yang seharusnya.
Timer yang didaftarkan oleh panggilan setInterval sebelumnya berkontribusi pada penundaan input seperti yang digambarkan di panel performa Chrome DevTools. Penundaan input yang ditambahkan menyebabkan callback peristiwa untuk interaksi berjalan lebih lambat dari yang seharusnya.

Jika timer terjadi dalam kode pihak pertama, Anda memiliki kontrol atasnya. Evaluasi apakah Anda memerlukannya, atau lakukan yang terbaik untuk mengurangi pekerjaan di dalamnya sebanyak mungkin. Namun, timer dalam skrip pihak ketiga adalah cerita yang 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 ya, hubungi vendor skrip pihak ketiga untuk menentukan apa yang dapat dilakukan untuk memperbaiki masalah performa yang mungkin disebabkan oleh skrip tersebut di situs Anda.

Hindari tugas yang panjang

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

Visualisasi durasi tugas memperpanjang penundaan input. Di bagian atas, interaksi terjadi tak lama setelah satu tugas berdurasi lama berjalan, sehingga menyebabkan penundaan input yang signifikan yang menyebabkan callback peristiwa berjalan jauh lebih lambat dari yang seharusnya. Pada dasarnya, interaksi terjadi pada waktu yang hampir bersamaan, tetapi tugas berdurasi lama dibagi menjadi beberapa tugas yang lebih kecil dengan menghasilkan, sehingga memungkinkan callback peristiwa interaksi berjalan 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 yang panjang.

Perhatikan tumpang-tindih interaksi

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

Penggambaran saat tugas dapat tumpang-tindih untuk 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 yang melakukan banyak interaksi dalam waktu singkat. Hal ini dapat terjadi saat pengguna mengetik di kolom formulir, tempat banyak interaksi keyboard dapat terjadi dalam waktu yang sangat singkat. Jika pekerjaan pada peristiwa tombol sangat mahal—seperti dalam kasus umum kolom pelengkapan otomatis tempat permintaan jaringan dibuat ke backend—Anda memiliki beberapa opsi:

  • Pertimbangkan sekali tekan input untuk membatasi jumlah waktu callback peristiwa dieksekusi dalam jangka waktu tertentu.
  • Gunakan AbortController untuk membatalkan permintaan fetch keluar sehingga thread utama tidak menjadi padat 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 requestAnimationFrame panggilan, yang dapat menghambat interaksi pengguna. Untuk mengatasi hal ini, 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 pada thread GPU dan komposit, dan bukan pada thread utama.

Kesimpulan

Meskipun penundaan input mungkin tidak mewakili sebagian besar waktu yang diperlukan interaksi Anda untuk berjalan, penting untuk memahami 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 yang panjang, dan menyadari potensi tumpang-tindih interaksi dapat membantu Anda mengurangi penundaan input, sehingga menghasilkan interaktivitas yang lebih cepat bagi pengguna situs Anda.

Gambar utama dari Unsplash, oleh Erik Mclean.