Memahami Interaction to Next Paint (INP)

1. Pengantar

Demo interaktif dan codelab untuk mempelajari Interaction to Next Paint (INP).

Diagram yang menggambarkan interaksi di thread utama. Pengguna memasukkan input saat tugas pemblokiran berjalan. Input ditunda hingga tugas tersebut selesai, setelah itu pemroses peristiwa pointerup, mouseup, dan click akan berjalan, lalu rendering dan pengecatan akan dimulai hingga frame berikutnya ditampilkan

Prasyarat

  • Pengetahuan tentang pengembangan HTML dan JavaScript.
  • Direkomendasikan: baca dokumentasi INP.

Yang Anda pelajari

  • Bagaimana interaksi pengguna dan penanganan interaksi tersebut memengaruhi responsivitas halaman.
  • Cara mengurangi dan menghilangkan penundaan untuk pengalaman pengguna yang lancar.

Yang Anda perlukan

  • Komputer yang dapat meng-clone kode dari GitHub dan menjalankan perintah npm.
  • Editor teks.
  • Chrome versi terbaru agar semua pengukuran interaksi berfungsi.

2. Memulai persiapan

Mendapatkan dan menjalankan kode

Kode ini dapat ditemukan di repositori web-vitals-codelabs.

  1. Clone repo di terminal Anda: git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git
  2. Buka direktori yang di-clone: cd web-vitals-codelabs/understanding-inp
  3. Instal dependensi: npm ci
  4. Mulai server web: npm run start
  5. Buka http://localhost:5173/understanding-inp/ di browser Anda

Ringkasan aplikasi

Di bagian atas halaman, terdapat penghitung Skor dan tombol Kenaikan. Demo klasik reaktivitas dan responsivitas.

Screenshot aplikasi demo untuk codelab ini

Di bawah tombol, ada empat pengukuran:

  • INP: skor INP saat ini, yang biasanya merupakan interaksi terburuk.
  • Interaksi: skor interaksi terbaru.
  • FPS: frame per detik thread utama halaman.
  • Timer: animasi timer yang sedang berjalan untuk membantu memvisualisasikan jank.

Entri FPS dan Timer sama sekali tidak diperlukan untuk mengukur interaksi. Ditambahkan hanya untuk mempermudah visualisasi responsivitas.

Cobalah

Coba berinteraksi dengan tombol Increment dan lihat skornya bertambah. Apakah nilai INP dan Interaksi berubah dengan setiap penambahan?

INP mengukur waktu yang diperlukan sejak pengguna berinteraksi hingga halaman benar-benar menampilkan pembaruan yang dirender kepada pengguna.

3. Mengukur interaksi dengan Chrome DevTools

Buka DevTools dari menu Alat Lainnya > Alat Developer, dengan mengklik kanan halaman dan memilih Periksa, atau dengan menggunakan pintasan keyboard.

Beralihlah ke panel Performa, yang akan Anda gunakan untuk mengukur interaksi.

Screenshot panel Performa DevTools bersama aplikasi

Selanjutnya, rekam interaksi di panel Performa.

  1. Tekan rekam.
  2. Berinteraksi dengan halaman (tekan tombol Increment).
  3. Hentikan perekaman.

Di linimasa yang dihasilkan, Anda akan menemukan jalur Interaksi. Luaskan dengan mengklik segitiga di sisi kiri.

Demonstrasi animasi tentang merekam interaksi menggunakan panel performa DevTools

Dua interaksi muncul. Perbesar yang kedua dengan men-scroll atau menahan tombol W.

Screenshot panel Performa DevTools, kursor mengarahkan ke interaksi di panel, dan tooltip yang mencantumkan waktu singkat interaksi

Dengan mengarahkan kursor ke interaksi, Anda dapat melihat bahwa interaksi tersebut berlangsung cepat, tidak menghabiskan waktu dalam durasi pemrosesan, dan menghabiskan waktu minimum dalam penundaan input dan penundaan presentasi, yang durasi pastinya akan bergantung pada kecepatan komputer Anda.

4. Pemroses peristiwa yang berjalan lama

Buka file index.js, dan hapus komentar fungsi blockFor di dalam pemroses peristiwa.

Lihat kode lengkap: click_block.html

button.addEventListener('click', () => {
  blockFor(1000);
  score.incrementAndUpdateUI();
});

Simpan file. Server akan melihat perubahan dan memuat ulang halaman untuk Anda.

Coba berinteraksi dengan halaman lagi. Interaksi kini akan terasa lebih lambat.

Trace performa

Buat rekaman lain di panel Performa untuk melihat tampilannya di sana.

Interaksi selama satu detik di panel Performa

Interaksi singkat yang sebelumnya hanya memerlukan waktu sepersekian detik, kini memerlukan waktu satu detik penuh.

Saat Anda mengarahkan kursor ke interaksi, perhatikan bahwa waktu hampir seluruhnya dihabiskan dalam "Durasi pemrosesan", yang merupakan jumlah waktu yang diperlukan untuk mengeksekusi callback pendengar peristiwa. Karena panggilan blockFor yang memblokir sepenuhnya berada dalam pemroses peristiwa, di situlah waktu berjalan.

5. Eksperimen: durasi pemrosesan

Coba berbagai cara untuk mengatur ulang tugas pemroses peristiwa guna melihat pengaruhnya terhadap INP.

Perbarui UI terlebih dahulu

Apa yang terjadi jika Anda menukar urutan panggilan js—memperbarui UI terlebih dahulu, lalu memblokir?

Lihat kode lengkap: ui_first.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
  blockFor(1000);
});

Apakah Anda melihat UI muncul sebelumnya? Apakah urutan memengaruhi skor INP?

Coba ambil rekaman aktivitas dan periksa interaksi untuk melihat apakah ada perbedaan.

Pemroses terpisah

Bagaimana jika Anda memindahkan pekerjaan ke pemroses peristiwa terpisah? Perbarui UI di satu pemroses peristiwa, dan blokir halaman dari pemroses terpisah.

Lihat kode lengkap: two_click.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('click', () => {
  blockFor(1000);
});

Seperti apa tampilannya di panel performa sekarang?

Berbagai jenis acara

Sebagian besar interaksi akan memicu banyak jenis peristiwa, dari peristiwa pointer atau tombol, hingga peristiwa pengarahan kursor, fokus/blur, dan peristiwa sintetis seperti beforechange dan beforeinput.

Banyak halaman nyata memiliki pemroses untuk banyak peristiwa yang berbeda.

Apa yang terjadi jika Anda mengubah jenis peristiwa untuk pemroses peristiwa? Misalnya, mengganti salah satu pemroses peristiwa click dengan pointerup atau mouseup?

Lihat kode lengkap: diff_handlers.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('pointerup', () => {
  blockFor(1000);
});

Tidak ada update UI

Apa yang terjadi jika Anda menghapus panggilan untuk memperbarui UI dari pemroses peristiwa?

Lihat kode lengkap: no_ui.html

button.addEventListener('click', () => {
  blockFor(1000);
  // score.incrementAndUpdateUI();
});

6. Hasil eksperimen durasi pemrosesan

Rekaman aktivitas performa: perbarui UI terlebih dahulu

Lihat kode lengkap: ui_first.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
  blockFor(1000);
});

Dengan melihat rekaman panel Performa saat mengklik tombol, Anda dapat melihat bahwa hasilnya tidak berubah. Meskipun update UI dipicu sebelum kode pemblokiran, browser tidak benar-benar mengupdate apa yang ditampilkan ke layar hingga setelah pemroses peristiwa selesai, yang berarti interaksi masih memerlukan waktu lebih dari satu detik untuk diselesaikan.

Interaksi satu detik di panel Performa

Trace performa: pemroses terpisah

Lihat kode lengkap: two_click.html

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('click', () => {
  blockFor(1000);
});

Sekali lagi, tidak ada perbedaan secara fungsional. Interaksi masih membutuhkan waktu satu detik penuh.

Jika Anda memperbesar interaksi klik, Anda akan melihat bahwa memang ada dua fungsi berbeda yang dipanggil sebagai hasil dari peristiwa click.

Seperti yang diharapkan, yang pertama—mengupdate UI—berjalan sangat cepat, sedangkan yang kedua membutuhkan waktu satu detik penuh. Namun, jumlah efeknya menghasilkan interaksi yang sama lambatnya bagi pengguna akhir.

Tampilan yang diperbesar pada interaksi selama satu detik dalam contoh ini, yang menunjukkan panggilan fungsi pertama yang memerlukan waktu kurang dari satu milidetik untuk diselesaikan

Trace performa: berbagai jenis peristiwa

button.addEventListener('click', () => {
  score.incrementAndUpdateUI();
});

button.addEventListener('pointerup', () => {
  blockFor(1000);
});

Hasil ini sangat mirip. Interaksinya masih satu detik penuh; satu-satunya perbedaan adalah bahwa pemroses click khusus update UI yang lebih pendek kini berjalan setelah pemroses pointerup yang memblokir.

Tampilan yang diperbesar dari interaksi berdurasi satu detik dalam contoh ini, yang menunjukkan pemroses peristiwa klik memerlukan waktu kurang dari satu milidetik untuk diselesaikan, setelah pemroses pointerup

Rekaman aktivitas performa: tidak ada update UI

Lihat kode lengkap: no_ui.html

button.addEventListener('click', () => {
  blockFor(1000);
  // score.incrementAndUpdateUI();
});
  • Skor tidak diperbarui, tetapi halaman masih diperbarui.
  • Animasi, efek CSS, tindakan komponen web default (input formulir), entri teks, penyorotan teks semuanya terus diperbarui.

Dalam hal ini, tombol akan beralih ke status aktif dan kembali saat diklik, yang memerlukan gambar oleh browser, yang berarti masih ada INP.

Karena pemroses peristiwa memblokir thread utama selama satu detik sehingga halaman tidak dapat dirender, interaksi masih memerlukan waktu satu detik penuh.

Merekam panel Performa menunjukkan interaksi yang hampir identik dengan yang terjadi sebelumnya.

Interaksi satu detik di panel Performa

Kesimpulan

Kode apa pun yang berjalan di pemroses peristiwa apa pun akan menunda interaksi.