Input akan dikirim ke Compositor
Ini adalah bagian terakhir dari 4 bagian blog yang membahas Chrome; menyelidiki bagaimana hal itu menangani kode kita untuk menampilkan sebuah situs web. Di postingan sebelumnya, kita melihat proses rendering dan mempelajari compositor. Dalam postingan ini, kita akan lihat bagaimana compositor memungkinkan interaksi yang mulus ketika masukan pengguna masuk.
Memasukkan peristiwa dari sudut pandang browser
Saat Anda mendengar "peristiwa input" Anda mungkin hanya berpikir mengetik di kotak teks atau klik {i>mouse<i}, tetapi dari sudut pandang browser, {i>input <i}berarti semua {i>gesture <i}dari pengguna. Scroll roda mouse adalah input dan sentuh atau mengarahkan mouse juga merupakan peristiwa input.
Saat {i>gesture <i}pengguna seperti menyentuh pada layar terjadi, proses {i>browser<i} adalah yang menerima
{i>gesture <i}pertama kali. Namun, proses browser hanya menyadari di mana {i>gesture <i}itu terjadi karena
konten di dalam tab ditangani oleh proses perender. Agar proses browser mengirimkan peristiwa
jenis (seperti touchstart
) dan koordinatnya untuk proses perender. Proses perender menangani
secara tepat dengan mencari target peristiwa dan menjalankan pemroses peristiwa yang terpasang.
Compositor menerima peristiwa input
Di posting sebelumnya, kita melihat bagaimana compositor bisa menangani gulir secara lancar dengan mengomposisikan lapisan raster. Jika tidak ada pemroses peristiwa input yang dilampirkan ke halaman, thread Compositor dapat membuat {i>frame<i} komposit baru yang sepenuhnya independen dari utas utama. Tapi bagaimana jika beberapa peristiwa pendengar dikaitkan ke halaman? Bagaimana thread compositor mengetahui apakah peristiwa tersebut memerlukan untuk ditangani?
Memahami wilayah yang tidak dapat di-scroll cepat
Karena menjalankan JavaScript adalah tugas utas utama, saat sebuah halaman disusun, utas compositor menandai region halaman yang memiliki pengendali peristiwa yang dilampirkan sebagai "Wilayah Tidak Cepat yang Dapat Di-scroll". Menurut memiliki informasi ini, thread compositor dapat memastikan untuk mengirim peristiwa input ke thread utama jika peristiwa terjadi di region tersebut. Jika peristiwa input berasal dari luar region ini, maka utas compositor berguna untuk menyusun bingkai baru tanpa menunggu utas utama.
Berhati-hatilah saat Anda menulis pengendali peristiwa
Pola penanganan peristiwa yang umum dalam pengembangan web adalah delegasi peristiwa. Karena balon acara, Anda dapat melampirkan satu pengendali peristiwa di elemen teratas dan mendelegasikan tugas berdasarkan target peristiwa. Anda mungkin telah melihat atau menulis kode seperti di bawah ini.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
Karena Anda hanya perlu menulis satu pengendali peristiwa untuk semua elemen, ergonomi peristiwa ini yang sangat menarik. Namun, jika Anda melihat kode ini dari sudut pandang browser , sekarang seluruh halaman ditandai sebagai wilayah yang tidak cepat dapat di-scroll. Ini berarti meskipun aplikasi tidak peduli dengan input dari bagian tertentu dari laman, thread compositor harus berkomunikasi dengan thread utama dan menunggunya setiap kali peristiwa input masuk. Dengan demikian, kemampuan scroll yang mulus dari compositor kalah.
Untuk mencegah hal ini terjadi, Anda dapat meneruskan opsi passive: true
di acara Anda
pemroses. Ini memberikan petunjuk ke browser bahwa Anda masih ingin
memproses peristiwa di thread utama,
tetapi compositor juga dapat melanjutkan dan menggabungkan {i>frame<i} baru.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
Memeriksa apakah acara dapat dibatalkan
Bayangkan Anda memiliki kotak di halaman yang Anda inginkan untuk membatasi arah scroll hanya untuk scroll horizontal.
Menggunakan opsi passive: true
di peristiwa pointer Anda berarti scroll halaman dapat berjalan lancar, tetapi
scroll vertikal mungkin sudah dimulai pada saat Anda ingin preventDefault
untuk membatasi
arah scroll. Anda dapat memeriksanya dengan menggunakan metode event.cancelable
.
document.body.addEventListener('pointermove', event => {
if (event.cancelable) {
event.preventDefault(); // block the native scroll
/*
* do what you want the application to do here
*/
}
}, {passive: true});
Atau, Anda dapat menggunakan aturan CSS seperti touch-action
untuk sepenuhnya menghilangkan pengendali peristiwa.
#area {
touch-action: pan-x;
}
Menemukan target peristiwa
Saat thread compositor mengirimkan peristiwa input ke thread utama, hal pertama yang akan dijalankan adalah hit untuk menemukan target peristiwa. Hit test menggunakan data kumpulan data paint yang dihasilkan dalam rendering untuk mencari tahu apa yang ada di bawah koordinat titik tempat peristiwa terjadi.
Meminimalkan pengiriman peristiwa ke thread utama
Dalam posting sebelumnya, kita membahas bagaimana tampilan biasa kita menyegarkan layar 60 kali per detik dan bagaimana kita harus mengikuti ritme untuk animasi yang mulus. Untuk input, layar sentuh biasa perangkat memberikan peristiwa sentuh 60-120 kali per detik, dan mouse biasa memberikan peristiwa 100 kali kedua. Peristiwa input memiliki fidelitas lebih tinggi daripada yang dapat dimuat ulang oleh layar.
Jika peristiwa berkelanjutan seperti touchmove
dikirim ke thread utama 120 kali per detik,
dapat memicu hit test dan eksekusi JavaScript secara berlebihan dibandingkan dengan seberapa lambat
layar dapat dimuat ulang.
Untuk meminimalkan panggilan yang berlebihan ke thread utama, Chrome menggabungkan peristiwa berkelanjutan (seperti
wheel
, mousewheel
, mousemove
, pointermove
, touchmove
) dan pengiriman yang tertunda hingga
tepat sebelum requestAnimationFrame
berikutnya.
Peristiwa terpisah apa pun seperti keydown
, keyup
, mouseup
, mousedown
, touchstart
, dan touchend
akan segera dikirim.
Gunakan getCoalescedEvents
untuk mendapatkan peristiwa intra-frame
Untuk sebagian besar aplikasi web, peristiwa gabungan sudah cukup untuk memberikan pengalaman pengguna yang baik.
Namun, jika Anda membangun hal-hal seperti menggambar aplikasi dan menempatkan jalur berdasarkan
Koordinat touchmove
, Anda bisa kehilangan di antara koordinat untuk menggambar garis yang mulus. Dalam kasus tersebut,
Anda dapat menggunakan metode getCoalescedEvents
dalam peristiwa pointer untuk mendapatkan informasi tentang
peristiwa yang bersatu.
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
});
Langkah berikutnya
Dalam seri ini, kami telah membahas cara kerja internal dari browser web. Jika Anda tidak pernah
memikirkan mengapa
DevTools merekomendasikan penambahan {passive: true}
pada pengendali peristiwa atau alasan Anda menulis async
di tag skrip Anda, saya harap rangkaian ini menjelaskan mengapa browser membutuhkannya.
untuk memberikan pengalaman web
yang lebih cepat dan lebih mulus.
Gunakan Lighthouse
Jika Anda ingin membuat kode Anda bagus untuk browser tetapi tidak tahu harus mulai dari mana, Lighthouse adalah alat yang menjalankan audit atas situs mana pun dan memberi Anda melaporkan apa yang sudah dilakukan dengan benar dan apa yang perlu diperbaiki. Membaca daftar audit juga memberikan gambaran hal-hal apa saja yang diperhatikan oleh browser.
Pelajari cara mengukur performa
Penyesuaian kinerja dapat bervariasi untuk situs yang berbeda, jadi penting bagi Anda untuk mengukur kinerja situs Anda dan menentukan apa yang paling sesuai untuk situs Anda. Tim Chrome DevTools memiliki beberapa tutorial tentang cara mengukur performa situs.
Menambahkan Kebijakan Fitur ke situs
Jika Anda ingin mengambil langkah tambahan, Kebijakan Fitur adalah
platform web yang dapat menjadi pagar pembatas
untuk Anda ketika Anda membangun proyek. Mengaktifkan
kebijakan fitur menjamin perilaku tertentu aplikasi dan mencegah Anda melakukan kesalahan.
Misalnya, jika Anda ingin memastikan aplikasi tidak akan pernah memblokir penguraian, Anda dapat menjalankan aplikasi di
kebijakan skrip sinkron. Jika sync-script: 'none'
diaktifkan, JavaScript yang memblokir parser akan
dicegah agar tidak dijalankan. Hal ini mencegah kode Anda memblokir parser, dan
tidak perlu khawatir menjeda parser.
Rangkuman
Ketika saya mulai membangun {i>website<i}, saya hampir hanya peduli tentang bagaimana saya akan menulis kode dan akan membantu saya menjadi lebih produktif. Hal-hal tersebut memang penting, tetapi kita juga harus memikirkan bagaimana mengambil kode yang kita tulis. {i>Browser<i} modern telah dan terus berinvestasi untuk berbagai cara untuk memberikan pengalaman web yang lebih baik bagi pengguna. Bersikap baik terhadap browser dengan mengatur kode kami, pada akhirnya, meningkatkan pengalaman pengguna Anda. Semoga Anda bergabung dengan saya dalam misi untuk bersikap baik terhadap browser!
Terima kasih banyak kepada semua yang telah meninjau draf awal rangkaian ini, termasuk (tetapi tidak terbatas kepada): Alex Russell, Paul Irish, Meggin Kearney, Eric Bidelman, Mathias Bynens, Addy Osmani, Kinuko Yasuda, Nasko Oskov, dan Charlie Reis.
Apakah Anda menikmati serial ini? Jika Anda memiliki pertanyaan atau saran untuk postingan mendatang, Saya ingin mendengar pendapat Anda di bagian komentar di bawah atau @kosamari di Twitter.