Kaynak yüklemeyi optimize edin

Önceki modülde, kritik oluşturma yolunun arkasındaki bazı teoriler ve oluşturmayı engelleyen ve ayrıştırıcıyı engelleyen kaynakların bir sayfanın ilk oluşturmasını nasıl geciktirebileceği ele alınmıştı. Bu konunun teorik temellerini öğrendiğinize göre, kritik oluşturma yolunu optimize etmeye yönelik bazı teknikleri öğrenmeye hazırsınız.

Bir sayfa yüklenirken HTML'sinde birçok kaynağa referans verilir. Bu kaynaklar, CSS aracılığıyla sayfaya görünüm ve düzen, JavaScript aracılığıyla da etkileşim sağlar. Bu modülde, bu kaynaklarla ve bir sayfanın yükleme süresini nasıl etkiledikleriyle ilgili bir dizi önemli kavram ele alınmaktadır.

Oluşturma engelleme

Önceki modülde de belirtildiği gibi, CSS, oluşturmayı engelleyen bir kaynaktır. Tarayıcının CSS Nesne Modeli (CSSOM) oluşturulana kadar herhangi bir içeriği oluşturmasını engeller. Tarayıcı, kullanıcı deneyimi açısından istenmeyen bir durum olan Biçimlendirilmemiş İçerik Flaşını (FOUC) önlemek için oluşturmayı engeller.

Önceki videoda, sayfayı herhangi bir stil olmadan görebileceğiniz kısa bir FOUC (Stil Uygulanmamış İçerik Yanıp Sönmesi) var. Ardından, sayfanın CSS'si ağdan yüklenmeyi tamamladığında tüm stiller uygulanır ve sayfanın stil içermeyen sürümü hemen stilli sürümle değiştirilir.

Genel olarak FOUC, normalde görmediğiniz bir şeydir ancak tarayıcının CSS indirilip sayfaya uygulanana kadar sayfanın oluşturulmasını neden engellediğini anlamak için bu kavramı bilmeniz önemlidir. Oluşturmayı engelleyen kaynaklar mutlaka istenmeyen bir durum değildir ancak CSS'nizi optimize ederek bu durumun süresini en aza indirmeniz gerekir.

Ayrıştırıcı engelleme

async veya defer özellikleri olmayan bir <script> öğesi gibi bir ayrıştırıcıyı engelleyen kaynak, HTML ayrıştırıcısını kesintiye uğratır. Ayrıştırıcı bir <script> öğesiyle karşılaştığında tarayıcının, HTML'nin geri kalanını ayrıştırmaya devam etmeden önce komut dosyasını değerlendirip yürütmesi gerekir. Komut dosyaları, DOM oluşturulurken DOM'u değiştirebileceği veya DOM'a erişebileceği için bu durum tasarımdan kaynaklanmaktadır.

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

Harici JavaScript dosyaları (async veya defer olmadan ya da type=module ile, bu da varsayılan olarak defer olur) kullanılırken dosya keşfedilip indirilene, ayrıştırılıp yürütülene kadar ayrıştırıcının çalışması engellenir. Satır içi JavaScript kullanılırken satır içi komut dosyası ayrıştırılıp yürütülene kadar ayrıştırıcı benzer şekilde engellenir.

Önyükleme tarayıcısı

Önceden yükleme tarayıcısı, birincil HTML ayrıştırıcısı kaynakları keşfetmeden önce ham HTML yanıtını tarayarak kaynakları bulup spekülatif olarak getiren ikincil bir HTML ayrıştırıcısı biçimindeki tarayıcı optimizasyonudur. Örneğin, ön yükleme tarayıcısı, HTML ayrıştırıcı CSS ve JavaScript gibi kaynakları getirip işlerken engellendiğinde bile tarayıcının <img> öğesinde belirtilen bir kaynağı indirmeye başlamasına olanak tanır.

Önceden yükleme tarayıcısından yararlanmak için kritik kaynaklar, sunucu tarafından gönderilen HTML işaretlemesine dahil edilmelidir. Aşağıdaki kaynak yükleme kalıpları, önceden yükleme tarayıcısı tarafından keşfedilemez:

  • background-image özelliği kullanılarak CSS ile yüklenen resimler. Bu resim referansları CSS'de yer alır ve önceden yükleme tarayıcısı tarafından keşfedilemez.
  • JavaScript kullanılarak DOM'a yerleştirilen <script> öğe işaretlemesi biçimindeki dinamik olarak yüklenen komut dosyaları veya dinamik import() kullanılarak yüklenen modüller.
  • JavaScript kullanılarak istemcide oluşturulan HTML. Bu tür işaretlemeler, JavaScript kaynaklarındaki dizelerde yer alır ve önceden yükleme tarayıcısı tarafından bulunamaz.
  • CSS @import beyanları.

Bu kaynak yükleme kalıplarının tümü geç keşfedilen kaynaklardır ve bu nedenle önceden yükleme tarayıcısından yararlanmaz. Mümkün olduğunca bunlardan kaçının. Ancak bu tür kalıplardan kaçınmak mümkün değilse kaynak keşfinde gecikmeleri önlemek için preload ipucunu kullanabilirsiniz.

CSS

CSS, bir sayfanın sunumunu ve düzenini belirler. Daha önce de belirtildiği gibi CSS, oluşturmayı engelleyen bir kaynaktır. Bu nedenle, CSS'nizi optimize etmek genel sayfa yükleme süresini önemli ölçüde etkileyebilir.

Sadeleştirme

CSS dosyalarının küçültülmesi, CSS kaynağının dosya boyutunu küçülterek indirme hızını artırır. Bu işlem, öncelikle kaynak CSS dosyasındaki boşluklar ve diğer görünmez karakterler gibi içerikleri kaldırarak ve sonucu yeni optimize edilmiş bir dosyaya aktararak gerçekleştirilir:

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

En temel biçimiyle CSS küçültme, web sitenizin FCP'sini ve bazı durumlarda LCP'sini iyileştirebilecek etkili bir optimizasyondur. Paketleyiciler gibi araçlar, üretim derlemelerinde bu optimizasyonu sizin için otomatik olarak gerçekleştirebilir.

Kullanılmayan CSS'yi kaldırın

Tarayıcının herhangi bir içeriği oluşturmadan önce tüm stil sayfalarını indirmesi ve ayrıştırması gerekir. Ayrıştırmanın tamamlanması için gereken süre, geçerli sayfada kullanılmayan stilleri de içerir. Tüm CSS kaynaklarını tek bir dosyada birleştiren bir paketleyici kullanıyorsanız kullanıcılarınız büyük olasılıkla mevcut sayfayı oluşturmak için gerekenden daha fazla CSS indiriyordur.

Geçerli sayfada kullanılmayan CSS'leri bulmak için Chrome Geliştirici Araçları'ndaki Kapsam aracını kullanın.

Chrome Geliştirici Araçları&#39;ndaki kapsam aracının ekran görüntüsü. Alt bölmede bir CSS dosyası seçilir ve mevcut sayfa düzeni tarafından kullanılmayan önemli miktarda CSS gösterilir.
Chrome Geliştirici Araçları'ndaki kapsam aracı, geçerli sayfa tarafından kullanılmayan CSS'yi (ve JavaScript'i) algılamak için kullanışlıdır. Sayfanın oluşturulmasını geciktirebilecek çok daha büyük bir CSS paketi göndermek yerine, CSS dosyalarını farklı sayfalar tarafından yüklenecek birden fazla kaynağa bölmek için kullanılabilir.

Kullanılmayan CSS'yi kaldırmanın iki yönlü etkisi vardır: İndirme süresini azaltmanın yanı sıra, tarayıcının daha az CSS kuralı işlemesi gerektiğinden oluşturma ağacı oluşturma işlemini de optimize edersiniz.

CSS @import beyanlarından kaçının

CSS'de @import bildirimleri kullanmak kolay gibi görünse de bu bildirimlerden kaçınmanız gerekir:

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

<link> öğesinin HTML'de çalışmasına benzer şekilde, CSS'deki @import bildirimi, bir stil sayfası içinden harici bir CSS kaynağını içe aktarmanıza olanak tanır. Bu iki yaklaşım arasındaki temel fark, HTML <link> öğesinin HTML yanıtının bir parçası olması ve bu nedenle @import bildirimiyle indirilen bir CSS dosyasından çok daha önce keşfedilmesidir.

Bunun nedeni, bir @import beyanının keşfedilebilmesi için bunu içeren CSS dosyasının öncelikle indirilmesi gerektiğidir. Bu durum, istek zinciri olarak bilinen bir duruma yol açar. Bu durum, CSS söz konusu olduğunda bir sayfanın ilk oluşturma işleminin ne kadar süreceğini geciktirir. Bir diğer dezavantaj ise @import bildirimi kullanılarak yüklenen stil sayfalarının önceden yükleme tarayıcısı tarafından keşfedilememesi ve bu nedenle geç keşfedilen, oluşturmayı engelleyen kaynaklar haline gelmesidir.

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

Çoğu durumda, @import yerine <link rel="stylesheet"> öğesini kullanabilirsiniz. <link> öğeleri, stil sayfalarının eşzamanlı olarak indirilmesine olanak tanır ve @import bildirimlerinin aksine genel yükleme süresini kısaltır. @import bildirimleri, stil sayfalarını ardışık olarak indirir.

Kritik CSS'leri satır içine alma

CSS dosyalarının indirilmesi, sayfanın FCP'sini artırabilir. Dokümanda kritik stillerin satır içi olarak eklenmesi <head> CSS kaynağı için ağ isteğini ortadan kaldırır ve doğru şekilde yapıldığında, kullanıcının tarayıcı önbelleği hazır olmadığında ilk yükleme sürelerini iyileştirebilir. Kalan CSS, eşzamansız olarak yüklenebilir veya <body> öğesinin sonuna eklenebilir.

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

Bununla birlikte, çok miktarda CSS'nin satır içi olarak eklenmesi, ilk HTML yanıtına daha fazla bayt ekler. HTML kaynakları genellikle çok uzun süre veya hiç önbelleğe alınamadığından, satır içi CSS'nin harici stil sayfalarında aynı CSS'yi kullanabilecek sonraki sayfalar için önbelleğe alınmadığı anlamına gelir. Ödünlerin çabaya değdiğinden emin olmak için sayfanızın performansını test edin ve ölçün.

CSS demoları

JavaScript

JavaScript, web'deki etkileşimlerin çoğunu destekler ancak bunun bir maliyeti vardır. Çok fazla JavaScript göndermek, sayfa yükleme sırasında web sayfanızın yavaş yanıt vermesine neden olabilir ve hatta etkileşimleri yavaşlatan yanıt verme sorunlarına yol açabilir. Bu sorunların her ikisi de kullanıcılar için can sıkıcı olabilir.

Oluşturmayı engelleyen JavaScript

defer veya async özellikleri olmadan <script> öğeleri yüklenirken tarayıcı, komut dosyası indirilene, ayrıştırılana ve yürütülene kadar ayrıştırma ve oluşturma işlemlerini engeller. Benzer şekilde, satır içi komut dosyaları da ayrıştırıcıyı komut dosyası ayrıştırılıp yürütülene kadar engeller.

async - defer

async ve defer, harici komut dosyalarının HTML ayrıştırıcıyı engellemeden yüklenmesine izin verirken type="module" içeren komut dosyaları (satır içi komut dosyaları dahil) otomatik olarak ertelenir. Ancak async ve defer arasında anlaşılması gereken bazı önemli farklar vardır.

Çeşitli komut dosyası yükleme mekanizmalarının gösterimi. Tüm mekanizmalar, ayrıştırıcı, getirme ve yürütme rollerini; async, defer, type=&#39;module&#39; gibi kullanılan çeşitli özelliklere ve üçünün kombinasyonuna göre ayrıntılı olarak açıklar.
https://html.spec.whatwg.org/multipage/scripting.html adresinden alınmıştır.

async ile yüklenen komut dosyaları indirildikten hemen sonra ayrıştırılıp yürütülürken defer ile yüklenen komut dosyaları HTML belgesi ayrıştırma işlemi tamamlandığında yürütülür. Bu işlem, tarayıcının DOMContentLoaded etkinliğiyle aynı anda gerçekleşir. Ayrıca, async komut dosyaları sırayla yürütülmeyebilir. defer komut dosyaları ise işaretlemede göründükleri sırayla yürütülür.

İstemci tarafı oluşturma

Genel olarak, kritik içerikleri veya bir sayfanın LCP öğesini oluşturmak için JavaScript kullanmaktan kaçınmanız gerekir. Bu, istemci tarafı oluşturma olarak bilinir ve tek sayfalık uygulamalarda (SPA'lar) yaygın olarak kullanılan bir tekniktir.

JavaScript ile oluşturulan işaretleme, önceden yükleme tarayıcısını atlar. Bunun nedeni, istemci tarafında oluşturulan işaretlemede bulunan kaynakların tarayıcı tarafından bulunamamasıdır. Bu durum, LCP resmi gibi önemli kaynakların indirilmesini geciktirebilir. Tarayıcı, LCP resmini yalnızca komut dosyası yürütüldükten ve öğe DOM'a eklendikten sonra indirmeye başlar. Buna karşılık, komut dosyası yalnızca keşfedildikten, indirildikten ve ayrıştırıldıktan sonra yürütülebilir. Bu durum, birbirini takip eden kritik istekler olarak bilinir ve kaçınılması gerekir.

Ayrıca, JavaScript kullanılarak oluşturulan işaretlemenin, gezinme isteğine yanıt olarak sunucudan indirilen işaretlemeye kıyasla uzun görevler oluşturma olasılığı daha yüksektir. HTML'nin istemci tarafında oluşturulmasının yoğun kullanımı, etkileşim gecikmesini olumsuz yönde etkileyebilir. Bu durum, özellikle bir sayfanın DOM'sinin çok büyük olduğu ve JavaScript'in DOM'u değiştirmesi durumunda önemli oluşturma çalışması gerektirdiği durumlarda geçerlidir.

Sadeleştirme

CSS'ye benzer şekilde, JavaScript'i küçültmek bir komut dosyası kaynağının dosya boyutunu küçültür. Bu, daha hızlı indirmelere yol açabilir ve tarayıcının JavaScript'i ayrıştırma ve derleme sürecine daha hızlı geçmesini sağlayabilir.

Ayrıca, JavaScript'in küçültülmesi, CSS gibi diğer öğelerin küçültülmesinden bir adım daha ileri gider. JavaScript küçültüldüğünde yalnızca boşluklar, sekmeler ve yorumlar gibi öğeler kaldırılmaz. Kaynak JavaScript'teki semboller de kısaltılır. Bu işleme bazen uglification adı verilir. Farkı görmek için aşağıdaki JavaScript kaynak kodunu kullanın:

// Unuglified JavaScript source code:
export function injectScript () {
  const scriptElement = document.createElement('script');
  scriptElement.src = '/js/scripts.js';
  scriptElement.type = 'module';

  document.body.appendChild(scriptElement);
}

Yukarıdaki JavaScript kaynak kodu küçültüldüğünde sonuç aşağıdaki kod snippet'ine benzer olabilir:

// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}

Önceki snippet'te, kaynakta bulunan, insanlar tarafından okunabilir değişkenin scriptElement kısaltılarak t yapıldığını görebilirsiniz. Çok sayıda komut dosyasına uygulandığında, web sitesinin üretim JavaScript'inin sağladığı özellikler etkilenmeden oldukça önemli tasarruflar elde edilebilir.

Web sitenizin kaynak kodunu işlemek için bir paketleyici kullanıyorsanız üretim derlemeleri için genellikle otomatik olarak küçültme işlemi yapılır. Örneğin Terser gibi karartıcılar da son derece yapılandırılabilir. Bu sayede, maksimum tasarruf elde etmek için karartma algoritmasının agresifliğini ayarlayabilirsiniz. Ancak, herhangi bir ad karartma aracının varsayılan ayarları genellikle çıktı boyutu ile özelliklerin korunması arasında doğru dengeyi kurmak için yeterlidir.

JavaScript demoları

Bilginizi test etme

Tarayıcıya birden fazla CSS dosyası yüklemenin en iyi yolu nedir?

CSS @import bildirimi.
Tekrar deneyin.
Birden fazla <link> öğesi.
Doğru!

Tarayıcı ön yükleme tarayıcısı ne işe yarar?

Bu, DOM ayrıştırıcının kaynakları keşfetmesinden önce keşfetmek için ham işaretlemeyi inceleyen ikincil bir HTML ayrıştırıcısıdır.
Doğru!
Bir HTML kaynağındaki <link rel="preload"> öğelerini algılar.
Tekrar deneyin.

Tarayıcı, JavaScript kaynaklarını indirirken neden HTML'nin ayrıştırılmasını varsayılan olarak geçici olarak engeller?

Biçimlendirilmemiş İçerik Yanıp Sönmesi'ni (FOUC) önlemek için.
Tekrar deneyin.
Çünkü JavaScript'i değerlendirmek çok fazla CPU kaynağı gerektiren bir görevdir ve HTML ayrıştırmayı duraklatmak, komut dosyalarının yüklenmesini tamamlamak için CPU'ya daha fazla bant genişliği sağlar.
Tekrar deneyin.
Bunun nedeni, komut dosyalarının DOM'u değiştirebilmesi veya başka bir şekilde erişebilmesidir.
Doğru!

Sonrakine geçme: Tarayıcıya kaynak ipuçlarıyla yardımcı olma

<head> öğesinde yüklenen kaynakların ilk sayfa yüklemesini ve çeşitli metrikleri nasıl etkileyebileceğini öğrendiğinize göre artık bir sonraki adıma geçebilirsiniz. Bir sonraki modülde, kaynak ipuçları ve bunların, tarayıcının kaynakları yüklemeye başlaması ve kaynaklar olmadan yapacağından daha erken bir zamanda kaynaklar arası sunuculara bağlantı açması için tarayıcıya nasıl değerli ipuçları verebileceği ele alınmaktadır.