Pemuatan resource Optimize

Di modul sebelumnya, beberapa teori di balik jalur rendering kritis dan bagaimana resource yang memblokir render dan pemblokir parser dapat menunda rendering awal halaman. Sekarang setelah Anda memahami beberapa teori di balik Anda siap mempelajari beberapa teknik untuk mengoptimalkan jalur rendering.

Saat halaman dimuat, banyak sumber daya dirujuk dalam HTML-nya yang menyediakan dengan tampilan dan tata letaknya melalui CSS, serta interaktivitasnya melalui JavaScript. Dalam modul ini, sejumlah konsep penting terkait sumber daya ini dan bagaimana pengaruhnya terhadap waktu muat laman telah dibahas.

Pemblokiran render

Seperti yang telah dibahas dalam modul sebelumnya, CSS adalah resource render-blocking, karena memblokir browser agar tidak merender konten apa pun hingga CSS Object Model (CSSOM) akan dibuat. Browser memblokir rendering untuk mencegah Flash Konten Tanpa Gaya (FOUC), yang tidak diinginkan dari sudut pandang pengalaman pengguna.

Dalam video sebelumnya, terdapat FOUC singkat tempat Anda dapat melihat halaman tanpa gaya apa pun. Selanjutnya, semua gaya diterapkan setelah CSS halaman selesai memuat dari jaringan, dan versi laman tanpa gaya ditampilkan segera diganti dengan versi {i>style<i}.

Secara umum, FOUC adalah sesuatu yang biasanya tidak Anda lihat, tetapi konsepnya penting dipahami agar Anda mengetahui alasan browser memblokir rendering halaman hingga CSS didownload dan diterapkan ke halaman. Pemblokiran render bukan tidak diinginkan, tetapi Anda ingin meminimalkan berapa lama kejadian itu menjaga CSS Anda tetap optimal.

Pemblokiran parser

Resource pemblokiran parser mengganggu parser HTML, seperti <script> tanpa atribut async atau defer. Ketika parser menemukan <script>, browser perlu mengevaluasi dan mengeksekusi skrip sebelum melanjutkan proses penguraian sisa HTML. Hal ini sesuai rencana, karena skrip mungkin mengubah atau mengakses DOM selama suatu waktu saat masih sedang dibuat.

<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>

Saat menggunakan file JavaScript eksternal (tanpa async atau defer), parser akan diblokir sejak file ditemukan hingga diunduh, diuraikan, dan telah dijalankan. Saat menggunakan JavaScript inline, parser juga diblokir hingga skrip sebaris akan diuraikan dan dieksekusi.

Pemindai pramuat

Pemindai pramuat adalah pengoptimalan browser dalam bentuk HTML sekunder yang memindai respons HTML mentah untuk menemukan dan mengambil secara spekulatif sumber daya sebelum parser HTML utama akan menemukannya. Sebagai misalnya, pemindai pramuat akan memungkinkan browser untuk 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 adalah tidak dapat ditemukan oleh pemindai pramuat:

  • Gambar dimuat oleh CSS menggunakan properti background-image. Gambar ini ada di CSS, dan tidak bisa ditemukan oleh pemindai pramuat.
  • Skrip yang dimuat secara dinamis dalam bentuk markup elemen <script> yang dimasukkan ke dalam DOM menggunakan JavaScript atau modul yang dimuat menggunakan import() dinamis.
  • HTML yang dirender pada klien menggunakan JavaScript. Markup tersebut berada dalam string dalam resource JavaScript, dan tidak dapat ditemukan oleh pramuat pemindai.
  • Deklarasi @import CSS.

Semua pola pemuatan sumber daya ini adalah sumber daya yang baru ditemukan, dan karenanya tidak mendapatkan manfaat dari pemindai pramuat. Hindari hal tersebut bila memungkinkan. Jika menghindari pola tersebut tidak mungkin dilakukan, tetapi Anda dapat menggunakan Petunjuk preload untuk menghindari penundaan penemuan resource.

CSS

CSS menentukan presentasi dan tata letak halaman. Seperti yang dijelaskan sebelumnya, CSS adalah sumber daya yang memblokir perenderan, jadi mengoptimalkan CSS dapat menimbulkan dampak terhadap waktu muat halaman secara keseluruhan.

Minifikasi

Memperkecil file CSS akan mengurangi ukuran file resource CSS, sehingga menjadikannya lebih kecil lebih cepat diunduh. Hal ini dilakukan terutama dengan menghapus konten dari sumber file CSS seperti spasi dan karakter tak terlihat lainnya, dan menghasilkan 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 mendasar, minifikasi CSS adalah pengoptimalan efektif yang dapat meningkatkan FCP situs Anda, dan bahkan mungkin LCP dalam beberapa kasus. Alat seperti pemaket dapat otomatis melakukan pengoptimalan ini untuk Anda dalam produksi build yang berbeda.

Hapus CSS yang tidak digunakan

Sebelum merender konten apa pun, browser perlu mengunduh dan mengurai semua spreadsheet gaya. Waktu yang dibutuhkan untuk menyelesaikan penguraian juga termasuk gaya yang tidak digunakan di halaman saat ini. Jika Anda menggunakan bundler yang menggabungkan semua CSS sumber daya ke dalam satu file, pengguna Anda cenderung mengunduh 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.

Screenshot alat cakupan di Chrome DevTools. File CSS dipilih di panel bawahnya, menunjukkan cukup banyak CSS yang tidak digunakan oleh tata letak halaman saat ini.
Alat cakupan di Chrome DevTools berguna untuk mendeteksi CSS (dan JavaScript) yang tidak digunakan oleh halaman saat ini. Ini dapat digunakan untuk membagi file CSS menjadi beberapa sumber daya untuk dimuat oleh laman yang berbeda, bukan mengirimkan paket CSS yang jauh lebih besar yang dapat menunda rendering halaman.

Menghapus CSS yang tidak digunakan memiliki dua efek: selain mengurangi download Anda mengoptimalkan konstruksi hierarki render, karena browser harus memproses lebih sedikit aturan CSS.

Menghindari deklarasi @import CSS

Meskipun tampaknya nyaman, Anda harus menghindari deklarasi @import di CSS:

/* Don't do this: */
@import url('style.css');

Serupa dengan cara kerja elemen <link> di HTML, deklarasi @import di CSS memungkinkan Anda mengimpor sumber daya CSS eksternal dari dalam lembar gaya. Tujuan perbedaan utama antara kedua pendekatan ini adalah elemen <link> HTML merupakan bagian dari respons HTML, sehingga ditemukan jauh lebih cepat daripada CSS file yang didownload oleh deklarasi @import.

Alasannya adalah agar deklarasi @import dapat ditemukan, file CSS yang memuatnya harus terlebih dahulu didownload. Ini menghasilkan rantai permintaan yang—dalam kasus CSS—keterlambatan berapa lama waktu yang dibutuhkan halaman untuk pertama kali dirender. Kelemahan lain adalah spreadsheet gaya yang dimuat menggunakan deklarasi @import tidak dapat ditemukan oleh pramuat, dan menjadi sumber daya pemblokir render yang baru ditemukan.

<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">

Dalam sebagian besar kasus, Anda dapat mengganti @import dengan menggunakan elemen <link rel="stylesheet">. Elemen <link> memungkinkan style sheet didownload secara serentak dan mengurangi waktu muat keseluruhan, dibandingkan @import deklarasi, yang mendownload style sheet secara berurutan.

CSS penting inline

Waktu yang diperlukan untuk mendownload file CSS dapat meningkatkan FCP halaman. {i>Inline<i} gaya kritis dalam dokumen <head> menghilangkan permintaan jaringan untuk Sumber daya CSS, dan—jika dilakukan dengan benar—dapat meningkatkan waktu pemuatan awal ketika {i>cache browser<i} pengguna tidak disiapkan. CSS yang tersisa dapat dimuat 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, membuat CSS dalam jumlah besar akan menambahkan lebih banyak byte Respons HTML. Karena sumber daya HTML sering kali tidak dapat disimpan di cache untuk waktu yang lama—atau pada semua—ini berarti bahwa CSS inline tidak di-cache untuk halaman berikutnya yang gunakan CSS yang sama di lembar gaya eksternal. Uji dan ukur metrik kinerja untuk memastikan dampak yang diperoleh sepadan dengan usaha yang dilakukan.

Demo CSS

JavaScript

JavaScript menggerakkan sebagian besar interaktivitas di web, tetapi hal ini membutuhkan biaya. Mengirimkan terlalu banyak JavaScript dapat membuat halaman web Anda lambat merespons selama halaman dimuat, dan bahkan dapat menyebabkan masalah responsivitas yang memperlambat interaksi yang dapat membingungkan pengguna.

JavaScript Pemblokir Render

Saat memuat elemen <script> tanpa atribut defer atau async, browser memblokir penguraian dan rendering hingga skrip didownload, diuraikan, dan telah dijalankan. Demikian pula, skrip inline memblokir parser hingga skrip diuraikan dan dieksekusi.

async vs. defer

async dan defer memungkinkan skrip eksternal dimuat tanpa memblokir HTML sementara skrip (termasuk skrip inline) dengan type="module" ditangguhkan secara otomatis. Namun, async dan defer memiliki beberapa perbedaan yang sangatlah penting untuk dipahami.

Penggambaran berbagai mekanisme pemuatan skrip, semuanya yang memerinci peran parser, pengambilan, dan eksekusi berdasarkan berbagai atribut yang digunakan seperti async, defer, type=&#39;module&#39; dan kombinasi dari ketiganya.
Bersumber dari https://html.spec.whatwg.org/multipage/scripting.html

Skrip yang dimuat dengan async akan segera diuraikan dan dieksekusi setelah didownload, sedangkan skrip yang dimuat dengan defer dieksekusi saat penguraian dokumen HTML selesai—ini terjadi bersamaan dengan peristiwa DOMContentLoaded browser. Selain itu, skrip async dapat mengeksekusi secara tidak berurutan, sedangkan skrip defer dieksekusi sesuai urutan kemunculannya dalam markup.

Rendering sisi klien

Umumnya, Anda harus menghindari penggunaan JavaScript untuk merender konten penting atau elemen LCP halaman Anda. Hal ini dikenal sebagai {i>rendering<i} sisi klien, dan merupakan teknik digunakan secara ekstensif dalam Aplikasi Web Satu Halaman (SPA).

Markup yang dirender oleh JavaScript menggantikan pemindai pramuat, karena resource yang ada dalam markup yang dirender klien tidak dapat ditemukan olehnya. Ini dapat menunda download resource penting, seperti gambar LCP. Browser hanya mulai mendownload gambar LCP setelah skrip dijalankan, dan menambahkan elemen ke DOM. Selanjutnya, skrip hanya dapat dieksekusi setelah ditemukan, diunduh, dan diuraikan. Ini dikenal sebagai permintaan kritis jaringan organisasi dan harus dihindari.

Selain itu, merender markup menggunakan JavaScript cenderung menghasilkan tugas yang lebih lama daripada markup yang didownload dari server sebagai respons terhadap navigasi permintaan. Penggunaan rendering sisi klien HTML secara negatif dapat berdampak negatif dan latensi interaksi. Terutama jika DOM halaman sangat besar, yang memicu tugas rendering yang signifikan saat JavaScript memodifikasi DOM.

Minifikasi

Serupa dengan CSS, meminimalkan JavaScript mengurangi ukuran file resource skrip. Hal ini dapat menghasilkan download yang lebih cepat, memungkinkan browser berpindah ke penguraian dan kompilasi JavaScript dengan lebih cepat.

Selain itu, minifikasi JavaScript selangkah lebih maju dibandingkan mengecilkan aset lain, seperti CSS. Saat diminifikasi, JavaScript tidak hanya dihilangkan hal-hal seperti spasi, tab, dan komentar, tetapi simbol di sumber JavaScript dipersingkat. Proses ini terkadang dikenal sebagai uglification. Kepada lihat 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 diringkas, hasilnya mungkin terlihat sesuatu 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, terlihat bahwa variabel yang dapat dibaca manusia scriptElement di sumber disingkat menjadi t. Ketika diterapkan pada kumpulan skrip, penghematannya bisa cukup signifikan, tanpa mempengaruhi fitur yang disediakan oleh JavaScript produksi situs web.

Jika Anda menggunakan bundler untuk memproses kode sumber situs web Anda, sering kali dilakukan secara otomatis untuk build produksi. Uglifier—seperti Terser, misalnya—juga sangat mudah dikonfigurasi, yang memungkinkan Anda menyesuaikan agresivitas algoritme uglifikasi untuk mencapai penghematan maksimum. Namun, setelan default untuk alat uglification apa pun biasanya cukup untuk memukul keseimbangan yang tepat antara ukuran {i>output<i} dan mempertahankan kemampuan.

Demo JavaScript

Menguji pengetahuan Anda

Apa cara terbaik untuk memuat beberapa file CSS di browser?

Deklarasi @import CSS.
Coba lagi.
Beberapa elemen <link>.
Benar.

Apa fungsi pemindai pramuat browser?

Ini adalah parser HTML sekunder yang memeriksa markup mentah untuk menemukan sumber daya sebelum parser DOM bisa menemukannya lebih cepat.
Benar.
Mendeteksi elemen <link rel="preload"> di sumber daya HTML.
Coba lagi.

Mengapa browser memblokir penguraian HTML untuk sementara secara default saat mendownload resource JavaScript?

Untuk mencegah Flash Konten Tanpa Gaya (FOUC).
Coba lagi.
Karena mengevaluasi JavaScript adalah tugas yang sangat intensif CPU, dan menjeda Penguraian HTML memberikan lebih banyak bandwidth ke CPU untuk menyelesaikan pemuatan skrip.
Coba lagi.
Karena skrip bisa memodifikasi atau mengakses DOM.
Benar.

Berikutnya: Membantu browser dengan petunjuk resource

Setelah Anda memahami cara pemuatan resource dalam elemen <head> memengaruhi pemuatan halaman awal dan berbagai metrik, kini saatnya Anda melanjutkan. Dalam modul, petunjuk resource dieksplorasi, dan bagaimana mereka dapat memberikan petunjuk browser untuk mulai memuat resource dan membuka koneksi ke lintas origin server lebih cepat daripada {i>browser<i} yang tidak akan bisa tanpanya.