Mengoptimalkan Interaksi ke Next Paint

Pelajari cara mengoptimalkan Interaction to Next Paint situs Anda.

Interaction to Next Paint (INP) adalah metrik Core Web Vitals stabil yang menilai responsivitas keseluruhan halaman terhadap interaksi pengguna dengan mengamati latensi semua interaksi yang memenuhi syarat yang terjadi selama masa aktif kunjungan pengguna ke halaman. Nilai INP akhir adalah interaksi terpanjang yang diamati (terkadang mengabaikan pencilan).

Untuk memberikan pengalaman pengguna yang baik, situs harus berupaya memiliki Interaction to Next Paint 200 milidetik atau kurang. Guna memastikan Anda mencapai target ini untuk sebagian besar pengguna, nilai minimum yang baik untuk diukur adalah persentil ke-75 pemuatan halaman, yang tersegmentasi di seluruh perangkat seluler dan desktop.

Nilai INP yang baik adalah 200 milidetik atau kurang, nilai yang buruk lebih besar dari 500 milidetik, dan apa pun di antaranya perlu ditingkatkan.

Bergantung pada situs, mungkin terdapat sedikit atau tidak ada interaksi—seperti halaman yang sebagian besar berisi teks dan gambar dengan sedikit atau tanpa elemen interaktif. Atau, dalam kasus situs seperti editor teks atau game, terdapat ratusan—bahkan ribuan—interaksi. Dalam kedua kasus tersebut, jika ada INP yang tinggi, pengalaman pengguna akan berisiko.

Perlu waktu dan upaya untuk meningkatkan INP, tetapi reward yang diperoleh adalah pengalaman pengguna yang lebih baik. Dalam panduan ini, jalan untuk meningkatkan INP akan dijelajahi.

Cari tahu penyebab INP buruk

Sebelum dapat memperbaiki interaksi yang lambat, Anda memerlukan data untuk memberi tahu apakah INP situs Anda buruk atau memerlukan peningkatan. Setelah memiliki informasi tersebut, Anda dapat melanjutkan ke lab untuk mulai mendiagnosis interaksi yang lambat, dan mencari solusi.

Menemukan interaksi lambat di lapangan

Idealnya, perjalanan Anda dalam mengoptimalkan INP akan dimulai dengan data lapangan. Hebatnya, data kolom dari penyedia Real User Monitoring (RUM) tidak hanya akan memberikan nilai INP halaman, tetapi juga data kontekstual yang menyoroti interaksi spesifik yang bertanggung jawab atas nilai INP itu sendiri, apakah interaksi terjadi selama atau setelah pemuatan halaman, jenis interaksi (klik, penekanan tombol, atau ketuk), dan informasi berharga lainnya.

Jika Anda tidak mengandalkan penyedia RUM untuk mendapatkan data kolom, panduan data kolom INP menyarankan untuk menggunakan Laporan Pengalaman Pengguna (CrUX) Chrome melalui PageSpeed Insights untuk membantu mengisi kekurangan data. CrUX adalah set data resmi program Core Web Vitals dan memberikan ringkasan metrik tingkat tinggi untuk jutaan situs, termasuk INP. Namun, CrUX sering kali tidak memberikan data kontekstual yang Anda dapatkan dari penyedia RUM untuk membantu Anda menganalisis masalah. Karena itu, kami tetap menyarankan agar situs menggunakan penyedia RUM jika memungkinkan, atau menerapkan solusi RUM mereka sendiri untuk melengkapi apa yang tersedia di CrUX.

Mendiagnosis interaksi lambat di lab

Idealnya, Anda dapat memulai pengujian di lab setelah memiliki data lapangan yang menunjukkan bahwa Anda memiliki interaksi yang lambat. Jika data lapangan tidak ada, ada beberapa strategi untuk mengidentifikasi interaksi lambat di lab. Strategi tersebut mencakup mengikuti alur pengguna umum dan menguji interaksi di sepanjang prosesnya, serta berinteraksi dengan halaman selama pemuatan—ketika thread utama sering kali tersibuk—untuk memunculkan interaksi lambat selama bagian penting pada pengalaman pengguna.

Mengoptimalkan interaksi

Setelah Anda mengidentifikasi interaksi lambat dan dapat mereproduksinya secara manual di lab, langkah selanjutnya adalah mengoptimalkannya. Interaksi dapat dibagi menjadi tiga fase:

  1. Penundaan input, yang dimulai saat pengguna memulai interaksi dengan halaman, dan berakhir saat callback peristiwa untuk interaksi mulai berjalan.
  2. Waktu pemrosesan, yang terdiri dari waktu yang diperlukan callback peristiwa untuk dijalankan hingga selesai.
  3. Penundaan presentasi, yaitu waktu yang diperlukan browser untuk menampilkan frame berikutnya yang berisi hasil visual interaksi.

Jumlah dari ketiga fase ini adalah latensi interaksi total. Setiap fase interaksi memberikan sejumlah waktu hingga total latensi interaksi, jadi penting untuk mengetahui bagaimana Anda bisa mengoptimalkan setiap bagian interaksi agar berjalan sesingkat mungkin.

Mengidentifikasi dan mengurangi penundaan input

Saat pengguna berinteraksi dengan halaman, bagian pertama dari interaksi tersebut adalah penundaan input. Bergantung pada aktivitas lain di halaman, penundaan input bisa cukup lama. Hal ini dapat disebabkan oleh aktivitas yang terjadi di thread utama (mungkin karena pemuatan skrip, penguraian, dan kompilasi), penanganan pengambilan, fungsi timer, atau bahkan dari interaksi lain yang terjadi secara berurutan dan saling tumpang tindih.

Apa pun sumber penundaan input interaksi, Anda ingin mengurangi penundaan input seminimal mungkin sehingga interaksi dapat mulai menjalankan callback peristiwa sesegera mungkin.

Hubungan antara evaluasi skrip dan tugas panjang selama startup

Aspek penting dari interaktivitas dalam siklus proses halaman adalah selama startup. Saat halaman dimuat, halaman tersebut akan dirender terlebih dahulu, tetapi penting untuk diingat bahwa hanya karena halaman telah dirender, bukan berarti halaman tersebut telah selesai dimuat. Bergantung pada jumlah resource yang diperlukan halaman agar berfungsi sepenuhnya, pengguna mungkin mencoba berinteraksi dengan halaman saat halaman masih dimuat.

Satu hal yang dapat memperpanjang penundaan input interaksi saat halaman dimuat adalah evaluasi skrip. Setelah file JavaScript diambil dari jaringan, browser masih memiliki pekerjaan yang harus dilakukan sebelum JavaScript dapat berjalan; pekerjaan itu mencakup penguraian skrip untuk memastikan sintaksnya valid, mengompilasinya menjadi bytecode, kemudian akhirnya mengeksekusinya.

Bergantung pada ukuran skrip, pekerjaan ini bisa menimbulkan tugas yang panjang di thread utama, yang akan menunda browser merespons interaksi pengguna lainnya. Agar halaman Anda tetap responsif terhadap input pengguna selama pemuatan halaman, penting untuk memahami hal-hal yang dapat dilakukan untuk mengurangi kemungkinan tugas yang lama saat pemuatan halaman sehingga halaman tetap cepat.

Mengoptimalkan callback peristiwa

Penundaan input hanyalah bagian pertama dari apa yang diukur INP. Anda juga harus memastikan bahwa callback peristiwa yang berjalan sebagai respons terhadap interaksi pengguna dapat diselesaikan secepat mungkin.

Sering menghasilkan thread utama

Saran umum terbaik dalam mengoptimalkan callback peristiwa adalah melakukan pekerjaan sesedikit mungkin di callback tersebut. Namun, logika interaksi Anda mungkin rumit, dan Anda mungkin hanya dapat sedikit mengurangi pekerjaan yang dilakukannya.

Jika hal ini terjadi di situs Anda, hal berikutnya yang dapat Anda coba adalah membagi pekerjaan di callback peristiwa menjadi tugas yang terpisah. Hal ini mencegah pekerjaan kolektif menjadi tugas panjang yang memblokir thread utama, yang memungkinkan interaksi lain yang seharusnya menunggu di thread utama berjalan lebih cepat.

setTimeout adalah salah satu cara untuk menghentikan tugas, karena callback yang diteruskan ke callback tersebut akan berjalan di tugas baru. Anda dapat menggunakan setTimeout sendiri atau memisahkan penggunaannya ke dalam fungsi terpisah untuk hasil yang lebih ergonomis.

Menghasilkan tanpa diskriminatif lebih baik daripada tidak menghasilkan sama sekali—namun, ada cara yang lebih bernuansa untuk menghasilkan thread utama, dan itu hanya melibatkan hasil segera setelah callback peristiwa yang memperbarui antarmuka pengguna sehingga logika rendering dapat berjalan lebih cepat.

Hasil untuk memungkinkan pekerjaan rendering berlangsung lebih cepat

Teknik hasil yang lebih canggih melibatkan penataan kode di callback peristiwa untuk membatasi apa yang dijalankan hanya ke logika yang diperlukan untuk menerapkan update visual untuk frame berikutnya. Segala sesuatu yang lain dapat ditangguhkan ke tugas berikutnya. Hal ini tidak hanya membuat callback tetap ringan dan gesit, tetapi juga meningkatkan waktu rendering untuk interaksi dengan tidak mengizinkan update visual memblokir kode callback peristiwa.

Misalnya, bayangkan sebuah editor rich text yang memformat teks saat Anda mengetik, sekaligus memperbarui aspek UI lain sebagai respons terhadap apa yang telah Anda tulis (seperti jumlah kata, menyorot kesalahan ejaan, dan masukan visual penting lainnya). Selain itu, aplikasi mungkin juga perlu menyimpan apa yang telah Anda tulis sehingga jika Anda keluar dan kembali, Anda tidak kehilangan pekerjaan apa pun.

Dalam contoh ini, empat hal berikut perlu terjadi sebagai respons terhadap karakter yang diketik oleh pengguna. Namun, hanya item pertama yang perlu dilakukan sebelum frame berikutnya ditampilkan.

  1. Perbarui kotak teks dengan teks yang diketik pengguna dan terapkan format yang diperlukan.
  2. Mengupdate bagian UI yang menampilkan jumlah kata saat ini.
  3. Jalankan logika untuk memeriksa kesalahan ejaan.
  4. Simpan perubahan terbaru (baik secara lokal atau ke database jarak jauh).

Kode untuk melakukannya mungkin terlihat seperti berikut:

textBox.addEventListener('input', (inputEvent) => {
  // Update the UI immediately, so the changes the user made
  // are visible as soon as the next frame is presented.
  updateTextBox(inputEvent);

  // Use `setTimeout` to defer all other work until at least the next
  // frame by queuing a task in a `requestAnimationFrame()` callback.
  requestAnimationFrame(() => {
    setTimeout(() => {
      const text = textBox.textContent;
      updateWordCount(text);
      checkSpelling(text);
      saveChanges(text);
    }, 0);
  });
});

Visualisasi berikut menunjukkan bagaimana penundaan update yang tidak penting hingga frame berikutnya dapat mengurangi waktu pemrosesan dan juga latensi interaksi secara keseluruhan.

Penggambaran interaksi keyboard dan tugas selanjutnya dalam dua skenario. Di gambar teratas, tugas penting render dan semua tugas latar belakang berikutnya berjalan secara sinkron hingga kesempatan untuk menampilkan frame telah tiba. Di gambar bawah, pekerjaan penting render akan dijalankan terlebih dahulu, lalu menghasilkan thread utama untuk menampilkan frame baru lebih cepat. Tugas latar belakang akan berjalan setelahnya.
Klik gambar di atas untuk melihat versi resolusi tinggi.

Meskipun penggunaan setTimeout() di dalam panggilan requestAnimationFrame() di contoh kode sebelumnya diakui bersifat sedikit esoterik, penggunaan ini adalah metode efektif yang berfungsi di semua browser untuk memastikan bahwa kode yang tidak penting tidak memblokir frame berikutnya.

Menghindari layout thrashing

Layout thrashing—terkadang disebut layout sinkron paksa—adalah masalah performa rendering saat tata letak terjadi secara sinkron. Hal ini terjadi saat Anda memperbarui gaya di JavaScript, lalu membacanya dalam tugas yang sama—dan ada banyak properti di JavaScript yang dapat menyebabkan layout thrashing.

Visualisasi layout thrashing seperti yang ditampilkan di panel performa Chrome DevTools.
Contoh layout thrashing, seperti yang ditunjukkan di panel performa Chrome DevTools. Tugas rendering yang melibatkan layout thrashing akan ditandai dengan segitiga merah di sudut kanan atas bagian stack panggilan, yang sering kali diberi label Recalculate Style atau Layout.

Layout thrashing adalah bottleneck kinerja karena dengan memperbarui gaya lalu segera meminta nilai gaya tersebut di JavaScript, browser akan dipaksa untuk melakukan pekerjaan tata letak sinkron yang seharusnya bisa ditunggu untuk tampil secara asinkron nanti setelah callback peristiwa selesai berjalan.

Minimalkan penundaan presentasi

Penundaan presentasi tanda interaksi membentang dari saat callback peristiwa interaksi selesai berjalan, hingga titik saat browser dapat menggambar frame berikutnya yang menunjukkan perubahan visual yang dihasilkan.

Minimalkan ukuran DOM

Jika DOM halaman kecil, pekerjaan rendering biasanya selesai dengan cepat. Namun, saat DOM menjadi sangat besar, pekerjaan rendering cenderung diskalakan seiring dengan bertambahnya ukuran DOM. Hubungan antara pekerjaan rendering dan ukuran DOM tidak linear, tetapi DOM besar memang membutuhkan lebih banyak pekerjaan untuk dirender daripada DOM kecil. DOM besar bermasalah dalam dua kasus:

  1. Selama render halaman awal, saat DOM besar memerlukan banyak upaya untuk merender status awal halaman.
  2. Sebagai respons terhadap interaksi pengguna, DOM yang besar dapat menyebabkan pembaruan rendering menjadi sangat mahal, dan karena itu meningkatkan waktu yang diperlukan browser untuk menampilkan bingkai berikutnya.

Perlu diingat bahwa ada kalanya DOM besar tidak dapat dikurangi secara signifikan. Meskipun ada pendekatan yang dapat Anda lakukan untuk mengurangi ukuran DOM, seperti meratakan DOM atau menambahkan ke DOM selama interaksi pengguna agar ukuran DOM awal Anda tetap kecil, teknik tersebut mungkin hanya berfungsi sejauh ini.

Gunakan content-visibility untuk merender elemen di luar layar secara lambat

Salah satu cara untuk membatasi jumlah pekerjaan rendering selama pemuatan halaman dan pekerjaan rendering sebagai respons terhadap interaksi pengguna adalah dengan bersandar pada properti content-visibility CSS, yang secara efektif memengaruhi rendering elemen dengan lambat saat mendekati area tampilan. Meskipun content-visibility memerlukan beberapa latihan agar dapat digunakan secara efektif, sebaiknya selidiki apakah hasilnya memiliki waktu rendering yang lebih rendah dan dapat meningkatkan INP halaman Anda.

Memperhatikan biaya performa saat merender HTML menggunakan JavaScript

Di mana ada HTML, ada penguraian HTML, dan setelah browser selesai mengurai HTML menjadi DOM, browser harus menerapkan gaya padanya, melakukan penghitungan tata letak, dan selanjutnya merender tata letak tersebut. Ini adalah biaya yang tidak dapat dihindari, tetapi bagaimana Anda dapat merender HTML.

Saat server mengirim HTML, HTML tersebut akan masuk di browser sebagai streaming. {i>Streaming<i} artinya respons HTML dari server datang dalam potongan-potongan. Browser mengoptimalkan cara menangani streaming dengan secara bertahap mengurai potongan streaming tersebut saat masuk, dan merendernya sedikit demi sedikit. Ini adalah pengoptimalan kinerja karena browser secara implisit menghasilkan secara berkala dan otomatis selama pemuatan halaman, dan Anda mendapatkannya secara gratis.

Meskipun kunjungan pertama ke situs web mana pun akan selalu melibatkan beberapa jumlah HTML, pendekatan yang umum dimulai dengan sedikit HTML awal, kemudian JavaScript digunakan untuk mengisi area konten. Pembaruan berikutnya pada area konten tersebut juga terjadi sebagai hasil dari interaksi pengguna. Ini biasanya disebut model aplikasi web satu halaman (SPA). Satu kelemahan dari pola ini adalah, dengan merender HTML menggunakan JavaScript pada klien, Anda tidak hanya dikenai biaya pemrosesan JavaScript untuk membuat HTML tersebut, tetapi juga browser tidak akan menghasilkan hingga selesai mengurai HTML tersebut dan merendernya.

Penting untuk diingat bahwa bahkan situs web yang bukan SPA mungkin akan melibatkan sejumlah rendering HTML melalui JavaScript sebagai hasil dari interaksi. Umumnya hal ini tidak menjadi masalah, selama Anda tidak merender HTML dalam jumlah besar pada klien, yang dapat menunda presentasi frame berikutnya. Namun, penting untuk memahami implikasi performa dari pendekatan ini untuk merender HTML di browser, dan bagaimana hal ini dapat memengaruhi respons situs Anda terhadap input pengguna jika Anda merender banyak HTML melalui JavaScript.

Kesimpulan

Meningkatkan INP situs Anda merupakan proses yang berulang. Ketika Anda memperbaiki interaksi lambat di lapangan, ada kemungkinan besar—terutama jika situs Anda menyediakan banyak interaktivitas—Anda akan mulai menemukan interaksi lambat lainnya, dan Anda juga harus mengoptimalkannya.

Kunci untuk meningkatkan INP adalah persistensi. Pada waktunya, Anda bisa meningkatkan responsivitas halaman Anda ke tempat di mana pengguna senang dengan pengalaman yang Anda berikan kepada mereka. Kemungkinan besar saat Anda mengembangkan fitur baru untuk pengguna, Anda mungkin perlu melalui proses yang sama dalam mengoptimalkan interaksi yang khusus untuk mereka. Ini akan membutuhkan waktu dan usaha, tetapi waktu dan usaha itu harus dihabiskan dengan baik.

Banner besar dari Unsplash, oleh David Pisnoy, dan dimodifikasi sesuai dengan lisensi Unsplash.