Jangan melawan pemindai pramuat browser

Cari tahu apa itu pemindai pramuat browser, bagaimana pemindai ini membantu meningkatkan performa, dan bagaimana Anda dapat menghindari gangguan terhadapnya.

Salah satu aspek yang sering diabaikan dalam mengoptimalkan page speed adalah memahami sedikit tentang internal browser. Browser melakukan pengoptimalan tertentu untuk meningkatkan performa dengan cara yang tidak dapat kita lakukan sebagai developer—tetapi hanya selama pengoptimalan tersebut tidak digagalkan secara tidak sengaja.

Salah satu pengoptimalan browser internal yang perlu dipahami adalah pemindai pramuat browser. Postingan ini akan membahas cara kerja pemindai pramuat—dan yang lebih penting, cara agar Anda tidak menghalangi cara kerjanya.

Apa yang dimaksud dengan pemindai pramuat?

Setiap browser memiliki parser HTML utama yang melakukan tokenisasi markup mentah dan memprosesnya menjadi model objek. Semua ini akan terus berjalan dengan lancar hingga parser dijeda saat menemukan resource pemblokiran, seperti stylesheet yang dimuat dengan elemen <link>, atau skrip yang dimuat dengan elemen <script> tanpa atribut async atau defer.

Diagram parser HTML.
Gbr. 1: Diagram yang menunjukkan bagaimana parser HTML utama browser dapat diblokir. Dalam hal ini, parser menemukan elemen <link> untuk file CSS eksternal, yang memblokir browser agar tidak mengurai bagian dokumen lainnya—atau bahkan merender bagian mana pun—hingga CSS didownload dan diurai.

Dalam kasus file CSS, rendering diblokir untuk mencegah flash of unstyled content (FOUC), yaitu saat versi halaman tanpa gaya dapat dilihat sekilas sebelum gaya diterapkan ke halaman tersebut.

Halaman beranda web.dev dalam status tanpa gaya (kiri) dan status bergaya (kanan).
Gbr. 2: Contoh simulasi FOUC. Di sebelah kiri adalah halaman depan web.dev tanpa gaya. Di sebelah kanan adalah halaman yang sama dengan gaya yang diterapkan. Status tanpa gaya dapat terjadi dalam sekejap jika browser tidak memblokir rendering saat stylesheet sedang didownload dan diproses.

Browser juga memblokir penguraian dan rendering halaman saat menemukan elemen <script> tanpa atribut defer atau async.

Alasannya adalah browser tidak dapat mengetahui secara pasti apakah skrip tertentu akan mengubah DOM saat parser HTML utama masih melakukan tugasnya. Inilah alasan mengapa praktik umum untuk memuat JavaScript di akhir dokumen adalah agar efek pemblokiran penguraian dan rendering menjadi minimal.

Ini adalah alasan yang tepat mengapa browser harus memblokir penguraian dan rendering. Namun, memblokir salah satu langkah penting ini tidak diinginkan, karena dapat menghambat proses dengan menunda penemuan resource penting lainnya. Untungnya, browser melakukan yang terbaik untuk mengurangi masalah ini melalui parser HTML sekunder yang disebut pemindai pramuat.

Diagram parser HTML utama (kiri) dan pemindai pramuat (kanan), yang merupakan parser HTML sekunder.
Gbr. 3: Diagram yang menggambarkan cara kerja pemindai pramuat secara paralel dengan parser HTML utama untuk memuat aset secara spekulatif. Di sini, parser HTML utama diblokir saat memuat dan memproses CSS sebelum dapat mulai memproses markup gambar dalam elemen <body>, tetapi pemindai pramuat dapat melihat ke depan dalam markup mentah untuk menemukan resource gambar tersebut dan mulai memuatnya sebelum parser HTML utama tidak diblokir.

Peran pemindai pramuat bersifat spekulatif, yang berarti pemindai ini memeriksa markup mentah untuk menemukan resource yang akan diambil secara oportunistik sebelum parser HTML utama menemukannya.

Cara mengetahui kapan pemindai pramuat berfungsi

Pemindai pramuat ada karena pemblokiran rendering dan penguraian. Jika kedua masalah performa ini tidak pernah ada, pemindai pramuat tidak akan terlalu berguna. Kunci untuk mengetahui apakah halaman web mendapatkan manfaat dari pemindai pramuat bergantung pada fenomena pemblokiran ini. Untuk melakukannya, Anda dapat memperkenalkan penundaan buatan untuk permintaan guna mengetahui tempat pemindai pramuat bekerja.

Ambil halaman ini yang berisi teks dan gambar dasar dengan stylesheet sebagai contoh. Karena file CSS memblokir rendering dan penguraian, Anda akan menyebabkan penundaan buatan selama dua detik untuk stylesheet melalui layanan proxy. Penundaan ini memudahkan Anda melihat di waterfall jaringan tempat pemindai pramuat bekerja.

Diagram waterfall jaringan WebPageTest mengilustrasikan penundaan buatan selama 2 detik yang diterapkan pada stylesheet.
Gbr. 4: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Meskipun stylesheet sengaja ditunda melalui proxy selama dua detik sebelum mulai dimuat, gambar yang terletak lebih jauh dalam payload markup ditemukan oleh pemindai pramuat.

Seperti yang dapat Anda lihat di waterfall, pemindai pramuat menemukan elemen <img> meskipun rendering dan penguraian dokumen diblokir. Tanpa pengoptimalan ini, browser tidak dapat mengambil berbagai hal secara oportunistik selama periode pemblokiran, dan lebih banyak permintaan resource akan bersifat berurutan, bukan serentak.

Setelah contoh sederhana tersebut, mari kita lihat beberapa pola di dunia nyata yang dapat mengalahkan pemindai pramuat—dan apa yang dapat dilakukan untuk memperbaikinya.

async skrip dimasukkan

Misalnya, Anda memiliki HTML di <head> yang menyertakan beberapa JavaScript inline seperti ini:

<script>
  const scriptEl = document.createElement('script');
  scriptEl.src = '/yall.min.js';

  document.head.appendChild(scriptEl);
</script>

Skrip yang dimasukkan adalah async secara default, jadi saat skrip ini dimasukkan, skrip akan berperilaku seolah-olah atribut async diterapkan padanya. Artinya, skrip akan berjalan secepat mungkin dan tidak memblokir rendering. Kedengarannya optimal, bukan? Namun, jika Anda menganggap bahwa <script> inline ini muncul setelah elemen <link> yang memuat file CSS eksternal, Anda akan mendapatkan hasil yang kurang optimal:

Diagram WebPageTest ini menunjukkan pemindaian pramuat yang gagal saat skrip dimasukkan.
Gbr. 5: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Halaman ini berisi satu stylesheet dan skrip async yang dimasukkan. Pemindai pramuat tidak dapat menemukan skrip selama fase pemblokiran render, karena skrip dimasukkan di klien.

Mari kita uraikan apa yang terjadi di sini:

  1. Pada detik ke-0, dokumen utama diminta.
  2. Pada detik ke-1,4, byte pertama permintaan navigasi tiba.
  3. Pada detik ke-2,0, CSS dan gambar diminta.
  4. Karena parser diblokir saat memuat stylesheet dan JavaScript inline yang memasukkan skrip async muncul setelah stylesheet tersebut pada detik ke-2,6, fungsi yang disediakan skrip tersebut tidak tersedia secepat mungkin.

Hal ini tidak optimal karena permintaan untuk skrip hanya terjadi setelah stylesheet selesai didownload. Tindakan ini akan menunda skrip agar tidak berjalan sesegera mungkin. Sebaliknya, karena elemen <img> dapat ditemukan dalam markup yang disediakan server, elemen tersebut ditemukan oleh pemindai pramuat.

Jadi, apa yang terjadi jika Anda menggunakan tag <script> reguler dengan atribut async, bukan memasukkan skrip ke dalam DOM?

<script src="/yall.min.js" async></script>

Berikut hasilnya:

Waterfall jaringan WebPageTest yang menggambarkan bagaimana skrip asinkron yang dimuat menggunakan elemen skrip HTML masih dapat ditemukan oleh pemindai pramuat browser, meskipun parser HTML utama browser diblokir saat mendownload dan memproses stylesheet.
Gbr. 6: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Halaman ini berisi satu stylesheet dan satu elemen async <script>. Pemindai pramuat menemukan skrip selama fase pemblokiran render, dan memuatnya secara bersamaan dengan CSS.

Mungkin ada beberapa godaan untuk menyarankan bahwa masalah ini dapat diatasi dengan menggunakan rel=preload. Cara ini pasti akan berhasil, tetapi mungkin memiliki beberapa efek samping. Lagi pula, mengapa menggunakan rel=preload untuk memperbaiki masalah yang dapat dihindari dengan tidak memasukkan elemen <script> ke dalam DOM?

Waterfall WebPageTest yang menunjukkan cara petunjuk resource rel=preload digunakan untuk meningkatkan penemuan skrip yang dimasukkan secara asinkron—meskipun dengan cara yang mungkin memiliki efek samping yang tidak diinginkan.
Gbr. 7: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Halaman ini berisi satu stylesheet dan skrip async yang dimasukkan, tetapi skrip async dipramuat untuk memastikan skrip tersebut ditemukan lebih cepat.

Pramuat "memperbaiki" masalah di sini, tetapi menimbulkan masalah baru: skrip async dalam dua demo pertama—meskipun dimuat di <head>—dimuat dengan prioritas "Rendah", sedangkan stylesheet dimuat dengan prioritas "Tertinggi". Dalam demo terakhir saat skrip async dipramuat, stylesheet masih dimuat dengan prioritas "Tertinggi", tetapi prioritas skrip telah dipromosikan menjadi "Tinggi".

Jika prioritas resource dinaikkan, browser akan mengalokasikan lebih banyak bandwidth untuk resource tersebut. Artinya, meskipun stylesheet memiliki prioritas tertinggi, prioritas skrip yang dinaikkan dapat menyebabkan perebutan bandwidth. Hal ini dapat menjadi faktor pada koneksi yang lambat, atau dalam kasus saat resource cukup besar.

Jawabannya sederhana: jika skrip diperlukan selama startup, jangan kalahkan pemindai pramuat dengan memasukkannya ke dalam DOM. Lakukan eksperimen sesuai kebutuhan dengan penempatan elemen <script>, serta dengan atribut seperti defer dan async.

Pemuatan lambat dengan JavaScript

Pemuatan lambat adalah metode yang bagus untuk menghemat data, yang sering diterapkan pada gambar. Namun, terkadang pemuatan lambat salah diterapkan ke gambar yang berada di "paruh atas".

Hal ini menimbulkan potensi masalah terkait visibilitas resource yang melibatkan pemindai pramuat, dan dapat menunda waktu yang diperlukan untuk menemukan referensi ke gambar, mendownloadnya, mendekodenya, dan menampilkannya. Mari kita ambil contoh markup gambar ini:

<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

Penggunaan awalan data- adalah pola umum dalam pemuat lambat yang didukung JavaScript. Saat gambar di-scroll ke area pandang, pemuat lambat akan menghapus awalan data-, yang berarti bahwa dalam contoh sebelumnya, data-src menjadi src. Update ini akan meminta browser untuk mengambil resource.

Pola ini tidak akan menimbulkan masalah hingga diterapkan ke gambar yang berada di area pandang selama startup. Karena pemindai pramuat tidak membaca atribut data-src dengan cara yang sama seperti atribut src (atau srcset), referensi gambar tidak ditemukan lebih awal. Lebih buruk lagi, pemuatan gambar tertunda hingga setelah JavaScript pemuat lambat didownload, dikompilasi, dan dieksekusi.

Diagram waterfall jaringan WebPageTest yang menunjukkan bagaimana gambar yang dimuat lambat yang berada di area pandang selama startup harus ditunda karena pemindai pramuat browser tidak dapat menemukan resource gambar, dan hanya dimuat saat JavaScript yang diperlukan untuk pemuatan lambat dimuat. Gambar ditemukan jauh lebih lambat daripada yang seharusnya.
Gbr. 8: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Resource gambar dimuat secara lambat tanpa alasan, meskipun terlihat di area pandang selama startup. Hal ini mengganggu pemindai pramuat dan menyebabkan penundaan yang tidak perlu.

Bergantung pada ukuran gambar—yang mungkin bergantung pada ukuran area pandang—gambar tersebut dapat menjadi elemen kandidat untuk Largest Contentful Paint (LCP). Jika pemindai pramuat tidak dapat mengambil resource gambar secara spekulatif lebih awal—mungkin saat stylesheet halaman memblokir rendering—LCP akan terpengaruh.

Solusinya adalah mengubah markup gambar:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

Ini adalah pola yang optimal untuk gambar yang berada di area pandang selama startup, karena pemindai pramuat akan menemukan dan mengambil resource gambar dengan lebih cepat.

Diagram waterfall jaringan WebPageTest yang menggambarkan skenario pemuatan untuk gambar di area pandang selama startup. Gambar tidak dimuat lambat, yang berarti gambar tidak bergantung pada skrip untuk dimuat, sehingga pemindai pramuat dapat menemukannya lebih cepat.
Gbr. 9: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Pemindai pramuat menemukan resource gambar sebelum CSS dan JavaScript mulai dimuat, sehingga browser dapat memulai pemuatan lebih awal.

Hasil dalam contoh yang disederhanakan ini adalah peningkatan LCP sebesar 100 milidetik pada koneksi yang lambat. Hal ini mungkin tidak terlihat seperti peningkatan yang besar, tetapi akan terlihat jika Anda mempertimbangkan bahwa solusinya adalah perbaikan markup yang cepat, dan bahwa sebagian besar halaman web lebih kompleks daripada kumpulan contoh ini. Artinya, kandidat LCP mungkin harus bersaing untuk mendapatkan bandwidth dengan banyak resource lain, sehingga pengoptimalan seperti ini menjadi makin penting.

Gambar latar CSS

Ingat bahwa pemindai pramuat browser memindai markup. Pemindai pramuat tidak memindai jenis resource lain, seperti CSS yang mungkin melibatkan pengambilan gambar yang direferensikan oleh properti background-image.

Seperti HTML, browser memproses CSS ke dalam model objeknya sendiri, yang dikenal sebagai CSSOM. Jika resource eksternal ditemukan saat CSSOM dibuat, resource tersebut akan diminta pada saat ditemukan, dan bukan oleh pemindai pramuat.

Misalnya, kandidat LCP halaman Anda adalah elemen dengan properti background-image CSS. Berikut adalah hal yang terjadi saat resource dimuat:

Diagram waterfall jaringan WebPageTest yang menggambarkan halaman dengan kandidat LCP yang dimuat dari CSS menggunakan properti background-image. Karena gambar kandidat LCP berada dalam jenis resource yang tidak dapat diperiksa oleh pemindai pramuat browser, pemuatan resource akan tertunda hingga CSS didownload dan diproses, sehingga menunda waktu render kandidat LCP.
Gbr. 10: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Kandidat LCP halaman adalah elemen dengan properti background-image CSS (baris 3). Gambar yang diminta tidak akan mulai diambil hingga parser CSS menemukannya.

Dalam hal ini, pemindai pramuat tidak terlalu dikalahkan karena tidak terlibat. Meskipun demikian, jika kandidat LCP di halaman berasal dari properti CSS background-image, Anda harus melakukan pramuat gambar tersebut:

<!-- Make sure this is in the <head> below any
     stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">

Petunjuk rel=preload tersebut kecil, tetapi membantu browser menemukan gambar lebih cepat daripada yang seharusnya:

Diagram waterfall jaringan WebPageTest yang menampilkan gambar latar CSS (yang merupakan kandidat LCP) dimuat jauh lebih cepat karena penggunaan petunjuk rel=preload. Waktu LCP meningkat sekitar 250 milidetik.
Gbr. 11: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Kandidat LCP halaman adalah elemen dengan properti background-image CSS (baris 3). Petunjuk rel=preload membantu browser menemukan gambar sekitar 250 milidetik lebih cepat daripada tanpa petunjuk.

Dengan petunjuk rel=preload, kandidat LCP ditemukan lebih cepat, sehingga menurunkan waktu LCP. Meskipun petunjuk tersebut membantu memperbaiki masalah ini, opsi yang lebih baik mungkin adalah menilai apakah kandidat LCP gambar Anda harus dimuat dari CSS atau tidak. Dengan tag <img>, Anda akan memiliki kontrol lebih besar atas pemuatan gambar yang sesuai untuk area pandang sekaligus memungkinkan pemindai pramuat menemukannya.

Menyisipkan terlalu banyak resource

Penyisipan adalah praktik yang menempatkan resource di dalam HTML. Anda dapat menyisipkan stylesheet dalam elemen <style>, skrip dalam elemen <script>, dan hampir semua resource lainnya menggunakan encoding base64.

Menyisipkan resource bisa lebih cepat daripada mendownloadnya karena permintaan terpisah tidak dikeluarkan untuk resource tersebut. Teks tersebut ada di dokumen, dan dimuat secara instan. Namun, ada kelemahan yang signifikan:

  • Jika Anda tidak meng-cache HTML—dan Anda tidak dapat melakukannya jika respons HTML bersifat dinamis—resource yang disisipkan tidak akan pernah di-cache. Hal ini memengaruhi performa karena resource yang di-inline tidak dapat digunakan kembali.
  • Meskipun Anda dapat meng-cache HTML, resource inline tidak dibagikan di antara dokumen. Hal ini mengurangi efisiensi caching dibandingkan dengan file eksternal yang dapat di-cache dan digunakan kembali di seluruh origin.
  • Jika Anda menyisipkan terlalu banyak, Anda akan menunda pemindai pramuat menemukan resource nanti dalam dokumen, karena mendownload konten tambahan yang disisipkan tersebut memerlukan waktu lebih lama.

Lihat halaman ini sebagai contoh. Dalam kondisi tertentu, kandidat LCP adalah gambar di bagian atas halaman, dan CSS berada dalam file terpisah yang dimuat oleh elemen <link>. Halaman ini juga menggunakan empat font web yang diminta sebagai file terpisah dari resource CSS.

Diagram waterfall jaringan WebPageTest dari halaman dengan file CSS eksternal yang memiliki empat font yang direferensikan di dalamnya. Gambar kandidat LCP ditemukan oleh pemindai pramuat pada waktu yang tepat.
Gbr. 12: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Kandidat LCP halaman adalah gambar yang dimuat dari elemen <img>, tetapi ditemukan oleh pemindai pramuat karena CSS dan font yang diperlukan untuk halaman dimuat dalam resource terpisah, yang tidak menunda pemindai pramuat melakukan tugasnya.

Sekarang, apa yang terjadi jika CSS dan semua font di-inline sebagai resource base64?

Diagram waterfall jaringan WebPageTest dari halaman dengan file CSS eksternal yang memiliki empat font yang direferensikan di dalamnya. Pemindai pramuat mengalami penundaan yang signifikan dalam menemukan gambar LCP .
Gbr. 13: Diagram waterfall jaringan WebPageTest dari halaman web yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Kandidat LCP halaman adalah gambar yang dimuat dari elemen <img>, tetapi penyisipan CSS dan empat resource font-nya di `` menunda pemindai pramuat menemukan gambar hingga resource tersebut didownload sepenuhnya.

Dampak penyisipan menghasilkan konsekuensi negatif untuk LCP dalam contoh ini—dan untuk performa secara umum. Versi halaman yang tidak menyisipkan apa pun akan merender gambar LCP dalam waktu sekitar 3,5 detik. Halaman yang menyisipkan semuanya tidak merender gambar LCP hingga lebih dari 7 detik.

Ada lebih banyak hal yang berperan di sini selain pemindai pramuat. Menyisipkan font bukanlah strategi yang baik karena base64 adalah format yang tidak efisien untuk resource biner. Faktor lain yang berperan adalah resource font eksternal tidak didownload kecuali jika ditentukan perlu oleh CSSOM. Jika font tersebut di-inline sebagai base64, font tersebut akan didownload, baik diperlukan untuk halaman saat ini maupun tidak.

Apakah pramuat dapat meningkatkan performa di sini? Oke. Anda dapat melakukan pramuat gambar LCP dan mengurangi waktu LCP, tetapi membuat HTML yang berpotensi tidak dapat di-cache menjadi terlalu besar dengan resource inline akan menimbulkan konsekuensi performa negatif lainnya. First Contentful Paint (FCP) juga terpengaruh oleh pola ini. Dalam versi halaman yang tidak memiliki elemen inline, FCP-nya sekitar 2,7 detik. Dalam versi yang semuanya di-inline, FCP-nya sekitar 5,8 detik.

Berhati-hatilah saat menyisipkan elemen ke dalam HTML, terutama resource berenkode base64. Secara umum, hal ini tidak direkomendasikan, kecuali untuk resource yang sangat kecil. Lakukan inlining sesedikit mungkin, karena terlalu banyak inlining dapat menimbulkan risiko.

Merender markup dengan JavaScript sisi klien

Tidak diragukan lagi: JavaScript pasti memengaruhi kecepatan halaman. Developer tidak hanya bergantung pada JavaScript untuk menyediakan interaktivitas, tetapi juga cenderung mengandalkannya untuk menayangkan konten itu sendiri. Hal ini memberikan pengalaman developer yang lebih baik dalam beberapa hal; tetapi manfaat bagi developer tidak selalu berarti manfaat bagi pengguna.

Satu pola yang dapat mengalahkan pemindai pramuat adalah merender markup dengan JavaScript sisi klien:

Waterfall jaringan WebPageTest yang menampilkan halaman dasar dengan gambar dan teks yang dirender sepenuhnya di sisi klien dalam JavaScript. Karena markup terdapat dalam JavaScript, pemindai pramuat tidak dapat mendeteksi resource apa pun. Semua resource juga tertunda karena waktu jaringan dan pemrosesan tambahan yang diperlukan framework JavaScript.
Gbr. 14: Diagram waterfall jaringan WebPageTest dari halaman web yang dirender sisi klien yang dijalankan di Chrome pada perangkat seluler melalui koneksi 3G yang disimulasikan. Karena kontennya terdapat dalam JavaScript dan mengandalkan framework untuk merender, resource gambar dalam markup yang dirender sisi klien disembunyikan dari pemindai pramuat. Pengalaman yang setara yang dirender server digambarkan dalam Gbr. 9.

Jika payload markup dimuat dan dirender sepenuhnya oleh JavaScript di browser, semua resource dalam markup tersebut tidak akan terlihat oleh pemindai pramuat. Hal ini menunda penemuan resource penting, yang tentu saja memengaruhi LCP. Dalam contoh ini, permintaan untuk gambar LCP sangat tertunda jika dibandingkan dengan pengalaman yang dirender server yang setara dan tidak memerlukan JavaScript untuk muncul.

Hal ini sedikit menyimpang dari fokus artikel ini, tetapi efek rendering markup pada klien jauh melampaui mengalahkan pemindai pramuat. Salah satunya, memperkenalkan JavaScript untuk mendukung pengalaman yang tidak memerlukannya akan menimbulkan waktu pemrosesan yang tidak perlu dan dapat memengaruhi Interaction to Next Paint (INP). Merender markup dalam jumlah yang sangat besar di klien lebih cenderung menghasilkan tugas berdurasi lama dibandingkan dengan jumlah markup yang sama yang dikirim oleh server. Alasannya—selain pemrosesan tambahan yang melibatkan JavaScript—adalah karena browser melakukan streaming markup dari server dan membagi rendering sedemikian rupa sehingga cenderung membatasi tugas berdurasi lama. Di sisi lain, markup yang dirender klien ditangani sebagai satu tugas monolitik, yang dapat memengaruhi INP halaman.

Perbaikan untuk skenario ini bergantung pada jawaban atas pertanyaan ini: Apakah ada alasan mengapa markup halaman Anda tidak dapat disediakan oleh server, bukan dirender di klien? Jika jawabannya "tidak", rendering sisi server (SSR) atau markup yang dihasilkan secara statis harus dipertimbangkan jika memungkinkan, karena akan membantu pemindai pramuat menemukan dan mengambil resource penting secara oportunistik terlebih dahulu.

Jika halaman Anda memerlukan JavaScript untuk menambahkan fungsi ke beberapa bagian markup halaman, Anda masih dapat melakukannya dengan SSR, baik dengan JavaScript vanilla, atau hidrasi untuk mendapatkan yang terbaik dari keduanya.

Bantu pemindai pramuat membantu Anda

Pemindai pramuat adalah pengoptimalan browser yang sangat efektif yang membantu halaman dimuat lebih cepat selama startup. Dengan menghindari pola yang mengalahkan kemampuannya untuk menemukan resource penting sebelumnya, Anda tidak hanya membuat pengembangan lebih mudah bagi diri sendiri, tetapi juga menciptakan pengalaman pengguna yang lebih baik yang akan memberikan hasil yang lebih baik dalam banyak metrik, termasuk beberapa data web.

Sebagai rangkuman, berikut hal-hal yang perlu Anda ketahui dari postingan ini:

  • Pemindai pramuat browser adalah parser HTML sekunder yang memindai lebih awal daripada parser utama jika parser utama diblokir untuk menemukan resource yang dapat diambil lebih cepat.
  • Resource yang tidak ada dalam markup yang disediakan oleh server pada permintaan navigasi awal tidak dapat ditemukan oleh pemindai pramuat. Cara pemindai pramuat dapat dikalahkan dapat mencakup (tetapi tidak terbatas pada):
    • Memasukkan resource ke dalam DOM dengan JavaScript, baik itu skrip, gambar, stylesheet, atau apa pun yang lebih baik berada dalam payload markup awal dari server.
    • Pemuatan lambat gambar atau iframe paruh atas menggunakan solusi JavaScript.
    • Merender markup di klien yang mungkin berisi referensi ke subresource dokumen menggunakan JavaScript.
  • Pemindai pramuat hanya memindai HTML. Pemindai ini tidak memeriksa konten resource lain—terutama CSS—yang mungkin menyertakan referensi ke aset penting, termasuk kandidat LCP.

Jika, karena alasan apa pun, Anda tidak dapat menghindari pola yang berdampak negatif pada kemampuan pemindai pramuat untuk mempercepat performa pemuatan, pertimbangkan petunjuk resource rel=preload. Jika Anda menggunakan rel=preload, uji di alat lab untuk memastikan bahwa alat tersebut memberikan efek yang Anda inginkan. Terakhir, jangan melakukan pramuat terlalu banyak resource, karena jika Anda memprioritaskan semuanya, tidak akan ada yang diprioritaskan.

Resource