JavaScript çerçevelerinde kaynak satır içine alma

JavaScript ekosisteminde Largest Contentful Paint'i iyileştirme.

Google, Aurora projesi kapsamında, Core Web Vitals'a göre iyi performans göstermeleri için popüler web çerçeveleriyle birlikte çalışıyor. Angular ve Next.js'de yazı tipi satır içi ekleme özelliği kullanıma sunulmuştur. Bu özellik bu makalenin ilk bölümünde açıklanmıştır. Bahsedeceğimiz ikinci optimizasyon ise, Angular KSA'da artık varsayılan olarak etkin olan ve Nuxt.js'de hâlâ uygulama işlemi devam eden kritik CSS satır içi satır öğesidir.

Yazı tipi satır içi ekleme

Aurora ekibi, yüzlerce uygulamayı analiz ettikten sonra geliştiricilerin genellikle index.html öğesinin <head> öğesinde referans vererek uygulamalarına yazı tipleri eklediğini tespit etti. Aşağıda, Material Icons'un dahil edildiği bir örneği görebilirsiniz:

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

Bu kalıp tamamen geçerli ve işlevsel olsa da uygulamanın oluşturulmasını engeller ve fazladan bir istek yapılmasını sağlar. Olan biteni daha iyi anlamak için yukarıdaki HTML'de referans verilen stil sayfasının kaynak koduna göz atın:

/* 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 {
  /*...*/
}

font-face tanımının, fonts.gstatic.com adresinde barındırılan harici bir dosyaya nasıl referans verdiğini görebilirsiniz. Uygulamayı yüklerken tarayıcının önce başlıkta referans verilen orijinal stil sayfasını indirmesi gerekir.

Web sitesinin sunucuya istek gönderip harici stil sayfasını nasıl indirmesi gerektiğini gösteren resim
İlk olarak, web sitesi yazı tipi stil sayfasını yükler.

Daha sonra, tarayıcı woff2 dosyasını indirir ve son olarak uygulamayı oluşturma işlemine devam edebilir.

Biri yazı tipi stil sayfası, diğeri yazı tipi dosyası için olmak üzere yapılan iki isteği gösteren resim.
Ardından, yazı tipinin yüklenmesi için istek gönderilir.

Optimize etme fırsatı olarak, ilk stil sayfasını derleme sırasında indirip index.html içine satır içi olarak ekleyebilirsiniz. Bu sayede, çalışma zamanında CDN'ye yapılan gidiş dönüş işleminin tamamı atlanır ve engelleme süresi kısalır.

Uygulama oluşturulurken CDN'ye bir istek gönderilir. Bu istek, stil sayfasını getirir ve HTML dosyasında satır içine alarak alana bir <link rel=preconnect> ekler. Bu tekniği uyguladığımızda aşağıdaki sonucu elde ederiz:

<!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>

Yazı tipi içe yerleştirme özelliği artık Next.js ve Angular'da kullanılabilir

Çerçeve geliştiricileri, temel araçta optimizasyon uyguladığında mevcut ve yeni uygulamaların bu özelliği etkinleştirmesini kolaylaştırarak iyileştirmeyi tüm ekosisteme getirir.

Bu iyileştirme, Next.js 10.2 ve Angular 11 sürümlerinden itibaren varsayılan olarak etkindir. Her ikisinde de Google ve Adobe yazı tiplerinin yerleştirilmesi desteklenir. Angular, ikinci sürümü 12.2 sürümünde kullanıma sunmayı umuyor.

GitHub'daki Next.js'de yazı tipi satır içine alma uygulamasını bulabilir ve bu optimizasyonu Angular bağlamında açıklayan videoyu izleyebilirsiniz.

Kritik CSS'leri satır içine alma

Kritik CSS'yi satır içi olarak ekleyerek İlk Zengin İçerikli Boyama (FCP) ve Largest Contentful Paint (LCP) metriklerini iyileştirmek de bir diğer geliştirmedir. Bir sayfanın kritik CSS'si, ilk oluşturulmasında kullanılan tüm stilleri içerir. Konu hakkında daha fazla bilgi edinmek için Kritik olmayan CSS'yi erteleme başlıklı makaleyi inceleyin.

Birçok uygulamanın, stili eşzamanlı olarak yüklediğini ve bu durumun uygulama oluşturmayı engellediğini tespit ettik. Bunun hızlı bir çözümü, stilleri eşzamansız olarak yüklemektir. Komut dosyalarını media="all" ile yüklemek yerine media özelliğinin değerini print olarak ayarlayın ve yükleme tamamlandıktan sonra özellik değerini all ile değiştirin:

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

Ancak bu uygulama, biçimlendirilmemiş içeriğin titremesine neden olabilir.

Türler yüklenirken sayfa titrer.

Yukarıdaki videoda, bir sayfanın oluşturulması gösterilmektedir. Bu sayfa, sayfa stilini eşzamansız olarak yükler. Yanıp sönme, tarayıcı önce stilleri indirmeye başladığı ve ardından HTML'yi oluşturmaya başladığı için gerçekleşir. Tarayıcı, stilleri indirdikten sonra bağlantı öğesinin onload etkinliğini tetikler, media özelliğini all olarak günceller ve stilleri DOM'a uygular.

HTML'nin oluşturulması ile stillerin uygulanması arasındaki süre boyunca sayfanın stili kısmen kaldırılır. Tarayıcı stilleri kullandığında titreme görüyoruz. Bu, kötü bir kullanıcı deneyimidir ve Kümülatif Yerleşim Kayması (CLS)'nda gerilemelere neden olur.

Eşzamansız stil yüklemeyle birlikte kritik CSS'yi satır içine yerleştirme, yükleme davranışını iyileştirebilir. Tarama aracı, stil sayfasındaki seçicilere bakarak ve bunları HTML ile eşleştirerek sayfada hangi stillerin kullanıldığını bulur. Bir eşleşme bulduğunda, ilgili stilleri kritik CSS'nin bir parçası olarak değerlendirir ve satır içine alır.

Bunu bir örnek üzerinde inceleyelim:

Yapılmaması gerekenler:
<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 {
  /* ... */
}

Satır içi yerleştirilmeden önceki örnek.

Yukarıdaki örnekte, critters, styles.css içeriğini okur ve ayrıştırır. Ardından, iki seçiciyi HTML ile eşleştirir ve section button.primary kullandığımızı keşfeder. Son olarak, critters, ilgili stilleri sayfanın <head> içine satır içi olarak ekler. Bu işlem sonucunda:

Yapılması gerekenler
<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>

Satır içi yerleştirildikten sonraki örnek.

Kritik CSS'yi HTML'ye yerleştirdikten sonra sayfanın titremesinin ortadan kalktığını göreceksiniz:

CSS satır içine alındıktan sonra sayfanın yüklenmesi.

Kritik CSS satır içine alma özelliği artık Angular'da kullanılabilir ve v12'de varsayılan olarak etkinleştirilmiştir. v11'i kullanıyorsanız angular.json içinde inlineCritical özelliğini true olarak ayarlayarak bu özelliği etkinleştirin. Next.js'de bu özelliği etkinleştirmek için next.config.js dosyanıza experimental: { optimizeCss: true } ekleyin.

Sonuçlar

Bu yayında, Chrome ile web çerçeveleri arasındaki bazı işbirliklerine değindik. Bir çerçeve yazarıysanız ve teknolojinizde ele aldığımız sorunlardan bazılarını tanıyorsanız bulgularımızın size benzer performans optimizasyonlarını uygulamaya teşvik etmesini umuyoruz.

İyileştirmeler hakkında daha fazla bilgi edinin. Core Web Vitals için yaptığımız optimizasyon çalışmalarının kapsamlı bir listesini Aurora'yı tanıtıyoruz başlıklı makalede bulabilirsiniz.