Dalam modul sebelumnya, beberapa teori di balik jalur rendering penting dieksplorasi, dan bagaimana resource pemblokiran render dan pemblokir parser dapat menunda rendering awal halaman. Setelah memahami beberapa teori di balik hal ini, Anda siap untuk mempelajari beberapa teknik untuk mengoptimalkan jalur rendering penting.
Saat halaman dimuat, banyak resource yang direferensikan dalam HTML-nya menyediakan halaman beserta tampilan dan tata letaknya melalui CSS, serta interaktivitasnya melalui JavaScript. Dalam modul ini, sejumlah konsep penting yang terkait dengan resource ini dan pengaruhnya terhadap waktu pemuatan halaman akan dibahas.
Pemblokiran rendering
Seperti yang telah dibahas dalam modul sebelumnya, CSS adalah resource pemblokiran render, karena memblokir browser agar tidak merender konten apa pun hingga Model Objek CSS (CSSOM) dibuat. Browser memblokir rendering untuk mencegah Flash of Unstyled Content (FOUC), yang tidak diinginkan dari sudut pandang pengalaman pengguna.
Dalam video sebelumnya, ada FOUC singkat tempat Anda dapat melihat halaman tanpa gaya apa pun. Selanjutnya, semua gaya akan diterapkan setelah CSS halaman selesai dimuat dari jaringan, dan versi halaman yang tidak bergaya akan segera diganti dengan versi yang telah diberi gaya.
Secara umum, FOUC adalah sesuatu yang biasanya tidak Anda lihat, tetapi konsep ini penting untuk dipahami agar Anda mengetahui alasan browser memblokir rendering halaman hingga CSS didownload dan diterapkan ke halaman. Pemblokiran rendering bukannya tidak diinginkan, tetapi Anda ingin meminimalkan durasinya dengan menjaga agar CSS Anda tetap optimal.
Pemblokiran parser
Resource pemblokiran parser mengganggu parser HTML, seperti elemen <script>
tanpa atribut async
atau defer
. Saat parser menemukan
elemen <script>
, browser harus mengevaluasi dan mengeksekusi skrip sebelum
melanjutkan dengan mengurai seluruh HTML. Hal ini sudah dirancang karena skrip dapat
mengubah atau mengakses DOM selama waktu ketika DOM masih dibuat.
<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>
Saat menggunakan file JavaScript eksternal (tanpa async
atau defer
), parser
akan diblokir dari saat file ditemukan hingga file didownload, diuraikan, dan
dieksekusi. Saat menggunakan JavaScript inline, parser akan diblokir juga hingga
skrip inline diurai dan dieksekusi.
Pemindai pramuat
Pemindai pramuat adalah pengoptimalan browser dalam bentuk parser HTML sekunder yang memindai respons HTML mentah untuk menemukan dan mengambil resource secara spekulatif sebelum parser HTML utama menemukannya. Misalnya, pemindai pramuat akan memungkinkan browser mulai mendownload
resource yang ditentukan dalam elemen <img>
, meskipun parser HTML diblokir
saat mengambil dan memproses resource seperti CSS dan JavaScript.
Untuk memanfaatkan pemindai pramuat, resource penting harus disertakan dalam markup HTML yang dikirim oleh server. Pola pemuatan resource berikut tidak dapat ditemukan oleh pemindai pramuat:
- Gambar yang dimuat oleh CSS menggunakan properti
background-image
. Referensi gambar ini berada dalam CSS, dan tidak dapat ditemukan oleh pemindai pramuat. - Skrip yang dimuat secara dinamis dalam bentuk markup elemen
<script>
yang dimasukkan ke DOM menggunakan JavaScript atau modul yang dimuat menggunakanimport()
dinamis. - HTML yang dirender pada klien menggunakan JavaScript. Markup tersebut terdapat dalam string di resource JavaScript, dan tidak dapat ditemukan oleh pemindai pramuat.
- Deklarasi
@import
CSS.
Semua pola pemuatan resource ini adalah resource yang terlambat ditemukan, sehingga
tidak mendapatkan manfaat dari pemindai pramuat. Hindari hal ini jika memungkinkan. Namun, jika
menghindari pola tersebut tidak memungkinkan, Anda mungkin dapat menggunakan
petunjuk preload
untuk menghindari penundaan penemuan resource.
CSS
CSS menentukan presentasi dan tata letak halaman. Seperti yang dijelaskan sebelumnya, CSS adalah resource pemblokir render, sehingga pengoptimalan CSS dapat berdampak besar terhadap waktu muat halaman secara keseluruhan.
Minifikasi
Meminifikasi file CSS akan mengurangi ukuran file resource CSS, sehingga membuatnya lebih cepat didownload. Hal ini terutama dicapai dengan menghapus konten dari file CSS sumber, seperti spasi dan karakter tak terlihat lainnya, serta meng-output hasilnya ke file yang baru dioptimalkan:
/* Unminified CSS: */
/* Heading 1 */
h1 {
font-size: 2em;
color: #000000;
}
/* Heading 2 */
h2 {
font-size: 1.5em;
color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
Dalam bentuknya yang paling dasar, minifikasi CSS adalah pengoptimalan efektif yang dapat meningkatkan FCP situs Anda, dan bahkan mungkin LCP dalam beberapa kasus. Alat seperti bundler dapat otomatis melakukan pengoptimalan ini untuk Anda dalam build produksi.
Hapus CSS yang tidak digunakan
Sebelum merender konten apa pun, browser harus mendownload dan mengurai semua style sheet. Waktu yang diperlukan untuk menyelesaikan penguraian juga mencakup gaya yang tidak digunakan di halaman saat ini. Jika Anda menggunakan bundler yang menggabungkan semua resource CSS menjadi satu file, pengguna Anda mungkin akan mendownload lebih banyak CSS daripada yang diperlukan untuk merender halaman saat ini.
Untuk menemukan CSS yang tidak digunakan untuk halaman saat ini, gunakan Alat cakupan di Chrome DevTools.
Menghapus CSS yang tidak digunakan memiliki efek dua kali lipat: selain mengurangi waktu download, Anda juga mengoptimalkan konstruksi hierarki render, karena browser perlu memproses lebih sedikit aturan CSS.
Menghindari deklarasi @import
CSS
Meskipun mungkin terlihat nyaman, Anda harus menghindari deklarasi @import
di CSS:
/* Don't do this: */
@import url('style.css');
Demikian pula dengan cara kerja elemen <link>
di HTML, deklarasi @import
di CSS memungkinkan Anda mengimpor resource CSS eksternal dari dalam style sheet. Perbedaan
utama antara kedua pendekatan ini adalah bahwa elemen <link>
HTML
adalah bagian dari respons HTML, dan oleh karena itu ditemukan jauh lebih cepat daripada file CSS
yang didownload oleh deklarasi @import
.
Alasannya adalah agar deklarasi @import
dapat
ditemukan, file CSS yang memuatnya harus terlebih dahulu didownload. Hal ini
mengakibatkan apa yang dikenal sebagai rantai permintaan, yang—dalam kasus CSS—menunda waktu yang diperlukan
untuk merender halaman pertama kali. Kekurangan lainnya adalah
style sheet yang dimuat menggunakan deklarasi @import
tidak dapat ditemukan oleh
pemindai pramuat, sehingga menjadi resource pemblokir render yang terlambat ditemukan.
<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">
Pada umumnya, Anda dapat mengganti @import
menggunakan
elemen <link rel="stylesheet">
. Elemen <link>
memungkinkan style sheet
didownload secara serentak dan mengurangi waktu pemuatan keseluruhan, bukan deklarasi @import
, yang mendownload style sheet secara berurutan.
CSS kritis inline
Waktu yang diperlukan untuk mendownload file CSS dapat meningkatkan FCP halaman. Memasukkan gaya penting dalam <head>
dokumen akan menghilangkan permintaan jaringan untuk resource CSS, dan—jika dilakukan dengan benar—dapat memperbaiki waktu pemuatan awal saat cache browser pengguna tidak disiapkan. CSS yang tersisa dapat dimuat
secara asinkron, atau ditambahkan di akhir elemen <body>
.
<head>
<title>Page Title</title>
<!-- ... -->
<style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
<!-- Other page markup... -->
<link rel="stylesheet" href="non-critical.css">
</body>
Kelemahannya, menyisipkan sejumlah besar CSS akan menambah lebih banyak byte ke respons HTML awal. Karena resource HTML sering kali tidak bisa di-cache untuk waktu yang lama—atau sama sekali—ini berarti CSS inline tidak di-cache untuk halaman berikutnya yang mungkin menggunakan CSS yang sama di style sheet eksternal. Uji dan ukur performa halaman Anda untuk memastikan komprominya sepadan dengan usaha Anda.
Demo CSS
JavaScript
JavaScript mendorong sebagian besar interaktivitas di web, tetapi hal ini menimbulkan biaya. Mengirimkan terlalu banyak JavaScript dapat membuat halaman web Anda lambat merespons selama pemuatan halaman, dan bahkan dapat menyebabkan masalah responsivitas yang memperlambat interaksi—keduanya dapat menjengkelkan bagi pengguna.
JavaScript yang memblokir perenderan
Saat memuat elemen <script>
tanpa atribut defer
atau async
, browser akan memblokir penguraian dan rendering hingga skrip didownload, diurai, dan dijalankan. Demikian pula, skrip inline memblokir parser hingga skrip diuraikan
dan dieksekusi.
async
versus defer
async
dan defer
memungkinkan skrip eksternal dimuat tanpa memblokir parser
HTML sementara skrip (termasuk skrip inline) dengan type="module"
ditangguhkan secara otomatis. Namun, async
dan defer
memiliki beberapa perbedaan yang
penting untuk dipahami.
Skrip yang dimuat dengan async
akan segera diuraikan dan dijalankan setelah didownload,
sedangkan skrip yang dimuat dengan defer
akan dijalankan saat penguraian dokumen HTML
selesai—hal ini terjadi bersamaan dengan peristiwa DOMContentLoaded
browser.
Selain itu, skrip async
dapat dijalankan secara tidak berurutan, sedangkan skrip defer
dijalankan sesuai urutan kemunculannya di markup.
Rendering sisi klien
Umumnya, sebaiknya hindari penggunaan JavaScript untuk merender konten penting atau elemen LCP halaman. Hal ini dikenal sebagai rendering sisi klien, dan merupakan teknik yang digunakan secara ekstensif dalam Aplikasi Web Satu Halaman (SPA).
Markup yang dirender oleh JavaScript menggantikan pemindai pramuat, karena resource yang terdapat dalam markup yang dirender klien tidak dapat ditemukan olehnya. Hal ini dapat menunda download resource penting, seperti gambar LCP. Browser hanya akan mulai mendownload gambar LCP setelah skrip dieksekusi, dan menambahkan elemen tersebut ke DOM. Oleh karena itu, skrip hanya dapat dijalankan setelah ditemukan, didownload, dan diurai. Hal ini dikenal sebagai rantai permintaan penting dan harus dihindari.
Selain itu, markup rendering menggunakan JavaScript lebih mungkin menghasilkan tugas panjang daripada markup yang didownload dari server sebagai respons terhadap permintaan navigasi. Penggunaan rendering HTML sisi klien yang ekstensif dapat berdampak negatif pada latensi interaksi. Hal ini terjadi terutama jika DOM halaman sangat besar, yang memicu pekerjaan rendering signifikan saat JavaScript mengubah DOM.
Minifikasi
Serupa dengan CSS, meminimalkan JavaScript akan mengurangi ukuran file resource skrip. Hal ini dapat menghasilkan download yang lebih cepat, sehingga browser dapat berpindah ke proses penguraian dan kompilasi JavaScript dengan lebih cepat.
Selain itu, minifikasi JavaScript selangkah lebih maju daripada mengecilkan aset lain, seperti CSS. Saat JavaScript diminifikasi, JavaScript tidak hanya dihilangkan dari hal-hal seperti spasi, tab, dan komentar, tetapi simbol dalam JavaScript sumber dipersingkat. Proses ini terkadang dikenal sebagai uglifikasi. Untuk melihat perbedaannya, ambil kode sumber JavaScript berikut:
// Unuglified JavaScript source code:
export function injectScript () {
const scriptElement = document.createElement('script');
scriptElement.src = '/js/scripts.js';
scriptElement.type = 'module';
document.body.appendChild(scriptElement);
}
Jika kode sumber JavaScript sebelumnya tidak jelas, hasilnya mungkin akan terlihat seperti cuplikan kode berikut:
// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
Dalam cuplikan sebelumnya, Anda dapat melihat bahwa variabel
scriptElement
yang dapat dibaca manusia dalam sumber disingkat menjadi t
. Jika diterapkan di seluruh koleksi skrip yang besar, penghematan bisa sangat signifikan, tanpa memengaruhi fitur yang disediakan JavaScript produksi situs.
Jika Anda menggunakan bundler untuk memproses kode sumber situs web Anda, uglifikasi sering kali dilakukan secara otomatis untuk build produksi. Uglifier—seperti Terser, misalnya—juga sangat mudah dikonfigurasi, sehingga Anda dapat menyesuaikan agresivitas algoritme uglification untuk mencapai penghematan maksimum. Namun, setelan default untuk setiap alat penghapusan biasanya cukup untuk mencapai keseimbangan yang tepat antara ukuran output dan mempertahankan kemampuan.
Demo JavaScript
Menguji pengetahuan Anda
Apa cara terbaik untuk memuat beberapa file CSS di browser?
@import
CSS.<link>
.Apa yang dilakukan pemindai pramuat browser?
<link rel="preload">
di
resource HTML.
Mengapa browser memblokir sementara penguraian HTML secara default saat mendownload resource JavaScript?
Berikutnya: Membantu browser dengan petunjuk resource
Setelah Anda memahami bagaimana resource yang dimuat dalam elemen <head>
dapat
memengaruhi pemuatan halaman awal dan berbagai metrik, sekarang saatnya untuk melanjutkan. Dalam modul
berikutnya, kita akan mempelajari petunjuk resource, dan bagaimana keduanya dapat memberikan petunjuk berharga bagi
browser untuk mulai memuat resource dan membuka koneksi ke server lintas-asal
lebih cepat daripada browser tanpa izin tersebut.