Mengoptimalkan Penundaan Input Pertama

Cara merespons interaksi pengguna dengan lebih cepat.

Saya mengklik tetapi tidak terjadi apa-apa! Mengapa saya tidak dapat berinteraksi dengan halaman ini? 😢

First Contentful Paint (FCP) dan Largest Contentful Paint (LCP) adalah metrik yang mengukur waktu yang diperlukannya untuk merender (gambar) konten secara visual di halaman. Meskipun penting, waktu paint tidak mencatat responsivitas pemuatan: atau seberapa cepat halaman merespons interaksi pengguna.

Penundaan Input Pertama (FID) adalah metrik Data Web Inti yang menangkap kesan pertama pengguna tentang interaktivitas dan responsivitas situs. Metrik ini mengukur waktu dari saat pengguna pertama kali berinteraksi dengan halaman hingga saat browser benar-benar dapat merespons interaksi tersebut. FID adalah metrik kolom dan tidak dapat disimulasikan di lingkungan lab. Interaksi pengguna nyata diperlukan untuk mengukur penundaan respons.

Nilai fid yang baik adalah 2,5 detik, nilai yang buruk lebih besar dari 4,0 detik dan apa pun di antaranya perlu perbaikan

Untuk membantu memprediksi FID di lab, sebaiknya gunakan Total Blocking Time (TBT). Keduanya mengukur hal yang berbeda, tetapi peningkatan pada TBT biasanya berkaitan dengan peningkatan FID.

Penyebab utama FID yang buruk adalah eksekusi JavaScript berat. Mengoptimalkan cara JavaScript mengurai, mengompilasi, dan mengeksekusi di halaman web Anda akan langsung mengurangi FID.

Eksekusi JavaScript berat

Browser tidak dapat merespons sebagian besar input pengguna saat mengeksekusi JavaScript di thread utama. Dengan kata lain, browser tidak dapat merespons interaksi pengguna saat thread utama sibuk. Untuk memperbaikinya:

Memecah Tugas yang Panjang

Jika Anda sudah mencoba mengurangi jumlah JavaScript yang dimuat di satu halaman, ada baiknya Anda membagi kode yang berjalan lama menjadi tugas asinkron yang lebih kecil.

Tugas Panjang adalah periode eksekusi JavaScript saat pengguna mungkin menemukan UI Anda tidak responsif. Setiap bagian kode yang memblokir thread utama selama 50 milidetik atau lebih dapat dicirikan sebagai Tugas Panjang. Tugas yang Panjang adalah tanda potensi JavaScript yang berlebihan (memuat dan mengeksekusi lebih dari yang mungkin diperlukan pengguna saat ini). Memisahkan tugas yang panjang dapat mengurangi penundaan input di situs Anda.

Tugas Panjang di Chrome DevTools
Chrome DevTools memvisualisasikan Tugas yang Panjang di Panel Performa

FID akan meningkat signifikan saat Anda mengadopsi praktik terbaik seperti pemisahan kode dan memecah Tugas Panjang Anda. Meskipun TBT bukan metrik kolom, metrik ini berguna untuk memeriksa progres guna pada akhirnya meningkatkan Waktu Untuk Interaktif (TTI) dan FID.

Optimalkan halaman Anda untuk kesiapan interaksi

Ada sejumlah penyebab umum untuk skor FID dan TBT yang buruk di aplikasi web yang sangat bergantung pada JavaScript:

Eksekusi skrip pihak pertama dapat menunda kesiapan interaksi

  • Penggelembungan ukuran JavaScript, waktu eksekusi yang berat, dan pemotongan yang tidak efisien dapat memperlambat seberapa cepat halaman dapat merespons input pengguna dan memengaruhi FID, TBT, dan TTI. Pemuatan kode dan fitur yang progresif dapat membantu menyebarkan tugas ini dan meningkatkan kesiapan interaksi.
  • Aplikasi yang dirender sisi server mungkin terlihat seperti menggambar piksel di layar dengan cepat, tetapi waspadalah terhadap interaksi pengguna yang diblokir oleh eksekusi skrip yang besar (misalnya hidrasi ulang untuk memasang pemroses peristiwa). Proses ini dapat memerlukan waktu beberapa ratus milidetik, terkadang bahkan detik, jika pemisahan kode berbasis rute digunakan. Sebaiknya alihkan lebih banyak logika di sisi server atau buat lebih banyak konten secara statis selama waktu build.

Berikut adalah skor TBT sebelum dan sesudah mengoptimalkan pemuatan skrip pihak pertama untuk aplikasi. Dengan memindahkan pemuatan (dan eksekusi) skrip yang mahal untuk komponen yang tidak penting dari jalur penting, pengguna dapat berinteraksi dengan halaman lebih cepat.

Peningkatan skor TBT di Lighthouse setelah mengoptimalkan skrip pihak pertama.

Pengambilan data dapat memengaruhi banyak aspek kesiapan interaksi

  • Menunggu waterfall pengambilan bertingkat (misalnya JavaScript dan pengambilan data untuk komponen) dapat memengaruhi latensi interaksi. Bertujuan untuk meminimalkan ketergantungan pada pengambilan data secara berjenjang.
  • Datastore inline yang besar dapat mendorong waktu penguraian HTML dan memengaruhi metrik paint dan interaksi. Upayakan untuk meminimalkan jumlah data yang perlu diproses pada sisi klien.

Eksekusi skrip pihak ketiga juga dapat menunda latensi interaksi

  • Banyak situs menyertakan tag dan analisis pihak ketiga yang dapat membuat jaringan tetap sibuk dan membuat thread utama tidak responsif secara berkala, sehingga memengaruhi latensi interaksi. Jelajahi pemuatan kode pihak ketiga sesuai permintaan (misalnya, jangan muat iklan paruh bawah sampai iklan di-scroll mendekati area pandang).
  • Dalam beberapa kasus, skrip pihak ketiga dapat menggantikan skrip pihak pertama dalam hal prioritas dan bandwidth di thread utama, yang juga menunda seberapa cepat halaman siap untuk berinteraksi. Coba prioritaskan pemuatan hal yang Anda yakini memberikan nilai terbesar kepada pengguna terlebih dahulu.

Menggunakan web worker

Thread utama yang diblokir adalah salah satu penyebab utama penundaan input. Pekerja web memungkinkan menjalankan JavaScript di thread latar belakang. Memindahkan operasi non-UI ke thread pekerja yang terpisah dapat mengurangi waktu pemblokiran thread utama dan akibatnya meningkatkan FID.

Pertimbangkan penggunaan library berikut untuk mempermudah penggunaan pekerja web di situs Anda:

  • Comlink: Library helper yang mengabstraksi postMessage dan membuatnya lebih mudah digunakan
  • Workway: Pengekspor pekerja web untuk tujuan umum
  • Workerize: Memindahkan modul ke pekerja web

Mengurangi waktu eksekusi JavaScript

Membatasi jumlah JavaScript di halaman akan mengurangi jumlah waktu yang diperlukan browser untuk mengeksekusi kode JavaScript. Hal ini akan mempercepat browser dalam mulai merespons setiap interaksi pengguna.

Untuk mengurangi jumlah JavaScript yang dieksekusi di halaman Anda:

  • Tunda JavaScript yang tidak digunakan
  • Meminimalkan polyfill yang tidak digunakan

Tunda JavaScript yang tidak digunakan

Secara default, semua JavaScript memblokir perenderan. Saat menemukan tag skrip yang ditautkan ke file JavaScript eksternal, browser harus menjeda aktivitasnya serta mendownload, mengurai, mengompilasi, dan mengeksekusi JavaScript tersebut. Oleh karena itu, Anda hanya boleh memuat kode yang diperlukan untuk halaman tersebut atau merespons input pengguna.

Tab Cakupan di Chrome DevTools dapat memberi tahu Anda seberapa banyak JavaScript yang tidak digunakan di halaman web Anda.

Tab Cakupan.

Untuk mengurangi JavaScript yang tidak digunakan:

  • Membagi paket Anda menjadi beberapa potongan kode
  • Tunda JavaScript yang tidak penting, termasuk skrip pihak ketiga, menggunakan async atau defer

Pemisahan kode adalah konsep membagi satu paket JavaScript besar menjadi potongan-potongan yang lebih kecil yang dapat dimuat secara bersyarat (juga dikenal sebagai pemuatan lambat). Sebagian besar browser yang lebih baru mendukung sintaksis impor dinamis, yang memungkinkan pengambilan modul sesuai permintaan:

import('module.js').then((module) => {
  // Do something with the module.
});

Mengimpor JavaScript secara dinamis pada interaksi pengguna tertentu (seperti mengubah rute atau menampilkan modal) akan memastikan bahwa kode yang tidak digunakan untuk pemuatan halaman awal hanya diambil saat diperlukan.

Selain dukungan browser umum, sintaksis impor dinamis dapat digunakan di berbagai sistem build.

  • Jika Anda menggunakan webpack, Rollup, atau Parcel sebagai pemaket modul, manfaatkan dukungan impor dinamisnya.
  • Framework sisi klien, seperti React, Angular, dan Vue menyediakan abstraksi untuk mempermudah pemuatan lambat pada tingkat komponen.

Selain pemisahan kode, selalu gunakan asinkron atau menunda untuk skrip yang tidak diperlukan untuk konten jalur kritis atau paruh atas.

<script defer src="…"></script>
<script async src="…"></script>

Kecuali jika ada alasan khusus untuk tidak melakukannya, semua skrip pihak ketiga harus dimuat dengan defer atau async secara default.

Meminimalkan polyfill yang tidak digunakan

Jika Anda menulis kode menggunakan sintaksis JavaScript modern dan mereferensikan API browser modern, Anda perlu melakukan transpilasi kode dan menyertakan polyfill agar dapat berfungsi di browser yang lebih lama.

Salah satu masalah performa utama saat menyertakan polyfill dan kode transpilasi di situs Anda adalah bahwa browser yang lebih baru tidak perlu mendownloadnya jika tidak memerlukannya. Untuk mengurangi ukuran JavaScript aplikasi Anda, minimalkan polyfill yang tidak digunakan sebanyak mungkin dan batasi penggunaannya di lingkungan yang membutuhkan polyfill.

Untuk mengoptimalkan penggunaan polyfill di situs Anda:

  • Jika Anda menggunakan Babel sebagai transpiler, gunakan @babel/preset-env untuk hanya menyertakan polyfill yang diperlukan untuk browser yang akan ditarget. Untuk Babel 7.9, aktifkan opsi bugfixes untuk lebih mengurangi polyfill yang tidak diperlukan
  • Gunakan pola modul/nomodule untuk mengirimkan dua paket terpisah (@babel/preset-env juga mendukung ini melalui target.esmodules)

    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js" defer></script>
    

    Banyak fitur ECMAScript lebih baru yang dikompilasi dengan Babel sudah didukung di lingkungan yang mendukung modul JavaScript. Dengan begitu, Anda akan menyederhanakan proses untuk memastikan bahwa hanya kode yang ditranspilasi yang akan digunakan untuk browser yang benar-benar membutuhkannya.

Developer tools

Tersedia sejumlah alat untuk mengukur dan men-debug FID:

Terima kasih kepada Philip Walton, Kayce Basques, Ilya Grigorik, dan Annie Sullivan atas ulasan mereka.