Penyelarasan resource dalam framework JavaScript

Meningkatkan Largest Contentful Paint di seluruh ekosistem JavaScript.

Sebagai bagian dari project Aurora, Google telah bekerja sama dengan framework web populer untuk memastikan framework tersebut berperforma baik sesuai dengan Core Web Vitals. Angular dan Next.js telah menerapkan inline font, yang dijelaskan di bagian pertama artikel ini. Pengoptimalan kedua yang akan kita bahas adalah penyematan CSS penting yang kini diaktifkan secara default di Angular CLI dan memiliki implementasi yang sedang dalam proses di Nuxt.js.

Penyusunan font

Setelah menganalisis ratusan aplikasi, tim Aurora menemukan bahwa developer sering menyertakan font dalam aplikasi mereka dengan mereferensikannya di elemen <head> dari index.html. Berikut adalah contoh tampilannya saat menyertakan Ikon Material:

<!doctype html>
<html lang="en">
<head>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  ...
</html>

Meskipun pola ini sepenuhnya valid dan berfungsi, pola ini memblokir rendering aplikasi dan memperkenalkan permintaan tambahan. Untuk lebih memahami apa yang terjadi, lihat kode sumber stylesheet yang dirujuk dalam HTML di atas:

/* fallback */
@font-face {
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}

.material-icons {
  /*...*/
}

Perhatikan cara definisi font-face mereferensikan file eksternal yang dihosting di fonts.gstatic.com. Saat memuat aplikasi, browser harus mendownload stylesheet asli yang direferensikan di head terlebih dahulu.

Gambar yang menampilkan cara situs web membuat permintaan ke server dan mengunduh stylesheet eksternal
Pertama, situs memuat stylesheet font.

Selanjutnya, browser akan mendownload file woff2, lalu akhirnya, browser dapat melanjutkan rendering aplikasi.

Gambar yang menampilkan dua permintaan yang dibuat, satu untuk stylesheet font, yang kedua untuk file font.
Selanjutnya, permintaan dibuat untuk memuat font.

Peluang untuk pengoptimalan adalah mendownload stylesheet awal pada waktu build dan menyisipkannya di index.html. Tindakan ini akan melewati seluruh perjalanan bolak-balik ke CDN saat runtime, sehingga mengurangi waktu pemblokiran.

Saat mem-build aplikasi, permintaan dikirim ke CDN, yang mengambil stylesheet dan menyisipkannya dalam file HTML, menambahkan <link rel=preconnect> ke domain. Dengan menerapkan teknik ini, kita akan mendapatkan hasil berikut:

<!doctype html>
<html lang="en">
<head>
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
  <style type="text/css">
  @font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
  ...
</html>

Penggabungan font kini tersedia di Next.js dan Angular

Saat developer framework menerapkan pengoptimalan dalam alat yang mendasarinya, mereka akan memudahkan aplikasi yang ada dan baru untuk mengaktifkannya, sehingga memberikan peningkatan pada seluruh ekosistem.

Peningkatan ini diaktifkan secara default dari Next.js v10.2 dan Angular v11. Keduanya memiliki dukungan untuk menyisipkan font Google dan Adobe. Angular akan memperkenalkan yang terakhir di v12.2.

Anda dapat menemukan implementasi pemasangan font inline di Next.js di GitHub, dan melihat video yang menjelaskan pengoptimalan ini dalam konteks Angular.

Menyelipkan CSS penting

Peningkatan lainnya mencakup peningkatan metrik First Contentful Paint (FCP) dan Largest Contentful Paint (LCP) dengan menyisipkan CSS penting. CSS penting halaman mencakup semua gaya yang digunakan pada rendering awalnya. Untuk mempelajari topik ini lebih lanjut, lihat Menunda CSS non-penting.

Kami mengamati bahwa banyak aplikasi memuat gaya secara sinkron, yang memblokir rendering aplikasi. Solusi cepatnya adalah memuat gaya secara asinkron. Daripada memuat skrip dengan media="all", tetapkan nilai atribut media ke print, dan setelah pemuatan selesai, ganti nilai atribut ke all:

<link rel="stylesheet" href="..." media="print" onload="this.media='all'">

Namun, praktik ini dapat menyebabkan konten tanpa gaya berkedip.

Halaman tampak berkedip saat gaya dimuat.

Video di atas menunjukkan rendering halaman, yang memuat gayanya secara asinkron. Flicker terjadi karena browser pertama-tama mulai mendownload gaya, lalu merender HTML yang berikutnya. Setelah mendownload gaya, browser akan memicu peristiwa onload elemen link, memperbarui atribut media menjadi all, dan menerapkan gaya ke DOM.

Selama waktu antara rendering HTML dan penerapan gaya, halaman tidak memiliki gaya sebagian. Saat browser menggunakan gaya, kita akan melihat kedipan, yang merupakan pengalaman pengguna yang buruk dan menyebabkan regresi dalam Pergeseran Tata Letak Kumulatif (CLS).

Penyisipan CSS penting, bersama dengan pemuatan gaya asinkron, dapat meningkatkan perilaku pemuatan. Alat critters menemukan gaya yang digunakan di halaman, dengan melihat pemilih dalam stylesheet dan mencocokkannya dengan HTML. Saat menemukan kecocokan, CSS akan mempertimbangkan gaya yang sesuai sebagai bagian dari CSS penting, dan menyejajarkannya.

Perhatikan contoh berikut:

Larangan
<head>
   <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">
</head>
<body>
  <section>
    <button class="primary"></button>
  </section>
</body>
/* styles.css */
section button.primary {
  /* ... */
}
.list {
  /* ... */
}

Contoh sebelum membuat inline.

Pada contoh di atas, critter akan membaca dan mengurai konten styles.css, setelah itu mencocokkan dua pemilih dengan HTML dan menemukan bahwa kita menggunakan section button.primary. Terakhir, makhluk akan menyisipkan gaya yang sesuai di <head> halaman sehingga menghasilkan:

Anjuran
<head>
  <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">
  <style>
  section button.primary {
    /* ... */
  }
  </style>
</head>
<body>
  <section>
    <button class="primary"></button>
  </section>
</body>

Contoh setelah penyertaan inline.

Setelah menyelaraskan CSS penting di HTML, Anda akan mendapati bahwa kedipan halaman telah hilang:

Halaman dimuat setelah CSS dibuat inline.

Penyisipan CSS penting kini tersedia di Angular dan diaktifkan secara default di v12. Jika Anda menggunakan v11, aktifkan dengan menetapkan properti inlineCritical ke true di angular.json. Untuk mengaktifkan fitur ini di Next.js, tambahkan experimental: { optimizeCss: true } ke next.config.js Anda.

Kesimpulan

Dalam postingan ini, kita telah membahas beberapa kolaborasi antara Chrome dan framework web. Jika Anda adalah penulis framework dan mengenali beberapa masalah yang kami tangani dalam teknologi Anda, kami harap temuan kami menginspirasi Anda untuk menerapkan pengoptimalan performa serupa.

Cari tahu lebih lanjut peningkatan ini. Anda dapat menemukan daftar lengkap pekerjaan pengoptimalan yang telah kami lakukan untuk Core Web Vitals dalam postingan Memperkenalkan Aurora.