Oğuzhan KARAGÜZEL

OĞUZHAN KARAGÜZEL

Yazılım geliştirici

Kaynak İpuçları: preload, prefetch, preconnect ve dns-prefetch

Yazar: Oğuzhan KARAGÜZEL ·

Tarayıcı bir sayfayı yüklerken HTML'i yukarıdan aşağıya okur ve kaynakları gördüğü sırayla ister. Sorun şu ki en önemli kaynaklar çoğu zaman geç fark ediliyor. Başlıkta kullandığınız font CSS dosyasının içinde tanımlı; CSS inmeden tarayıcı o fonttan haberdar olmuyor. Büyük kapak görseli CSS'te arka plan olarak verilmişse ya da JavaScript ile ekleniyorsa, tarayıcı onu en son görüyor. Kaynak ipuçları (resource hints), tarayıcıya "buna birazdan ihtiyacın olacak, şimdiden hazırlan" demenin yolu. Bu yazıda dns-prefetch, preconnect, preload ve prefetch arasındaki farkları, fetchpriority özelliğini, font yüklemeyi ve sık yapılan hataları anlatacağım.

Bir isteğin yolculuğu: DNS, TCP ve TLS

Tarayıcı başka bir alan adındaki bir dosyayı (mesela bir CDN'deki fontu) indirmeden önce o sunucuyla bağlantı kurmak zorunda. Dosya daha istenmeden şu adımlar yaşanıyor:

  1. DNS sorgusu: cdn.example.com gibi bir alan adı sunucunun IP adresine çevrilir.
  2. TCP el sıkışması: Tarayıcı ile sunucu bağlantıyı açmak için karşılıklı mesaj gönderir (SYN, SYN-ACK, ACK).
  3. TLS el sıkışması: HTTPS için şifreleme anahtarlarında anlaşılır. TLS 1.3'te bu bir gidiş-dönüş, TLS 1.2'de iki gidiş-dönüş sürer.
  4. İstek: Dosyanın kendisi ancak bundan sonra istenir.

Her adım, tarayıcı ile sunucu arasında en az bir gidiş-dönüş (RTT) demek. Masaüstünde bu birkaç on milisaniye tutuyor. Mobil bağlantılarda ise bir gidiş-dönüşün 100 milisaniyeyi geçmesi çok normal; yeni bir alan adıyla bağlantı kurmak tek başına 300 milisaniyeyi bulabiliyor. İlk iki kaynak ipucu bu bekleme süresini öne çekiyor.

dns-prefetch ve preconnect: bağlantıyı önden kurmak

dns-prefetch: sadece adresi çöz

dns-prefetch, tarayıcıdan sadece alan adının IP adresini önceden bulmasını istiyor. Bağlantı kurulmuyor, dosya inmiyor:

HTML
<link rel="dns-prefetch" href="https://cdn.example.com">

Maliyeti çok düşük bir ipucu. Sayfanın ilerleyen kısımlarında kullanılma ihtimali olan üçüncü taraf alan adları için uygun: bir yorum sistemi, bir harita ya da kullanıcı tıklayınca açılan bir video oynatıcı. Eski tarayıcılar da desteklediği için preconnect'in yanına yedek olarak eklenebiliyor.

preconnect: bağlantıyı önceden kur

preconnect bir adım daha ileri gidip DNS, TCP ve TLS adımlarının üçünü de önceden tamamlıyor. Dosya istendiğinde bağlantı hazır oluyor:

HTML
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.gstatic.com">

Buradaki crossorigin boşuna orada değil. Fontlar gibi CORS ile istenen dosyalar ayrı bir bağlantı havuzu kullanıyor. crossorigin yazmadan açtığınız bağlantı font isteği için kullanılamıyor, tarayıcı ikinci bir bağlantı açıyor ve ipucunuz boşa gidiyor.

preconnect'i dikkatli kullanın. Açılan her bağlantı hem tarayıcıya hem sunucuya iş çıkarıyor. Birkaç saniye içinde kullanılmayan bağlantıyı tarayıcı kapatıyor ve yapılan iş çöpe gidiyor. Genel kural şu: preconnect'i sadece sayfanın ilk saniyelerinde kesin kullanılacak en kritik iki üç alan adına verin, gerisine dns-prefetch yeter. Kendi alan adınız için ipucuna gerek yok, HTML'in geldiği bağlantı zaten açık.

preload: kritik dosyayı hemen indir

preload bağlantıyla yetinmiyor, dosyanın kendisini yüksek öncelikle indirmeye başlıyor. Bu sayfada kesin kullanılacak ama tarayıcının geç fark edeceği dosyalar için:

HTML
<!-- CSS içinde tanımlı başlık fontu -->
<link rel="preload" href="/fonts/inter-700.woff2" as="font" type="font/woff2" crossorigin>

<!-- CSS arka planı olarak verilen kapak görseli -->
<link rel="preload" href="/img/kapak.webp" as="image" fetchpriority="high">

Dikkat etmeniz gerekenler:

  • as zorunlu. Tarayıcı dosyanın türünü buradan anlıyor ve önceliği de buna göre veriyor. as eksik ya da yanlışsa dosya daha sonra kullanılırken tanınmıyor ve ikinci kez iniyor.
  • Font preload ederken crossorigin şart, font kendi alan adınızda olsa bile. Fontlar her zaman CORS ile isteniyor; crossorigin olmadan preload ettiğiniz font kullanılmıyor ve yine iki kez iniyor.
  • Kullanılmayan preload uyarı veriyor. Preload ettiğiniz dosya sayfa yüklendikten sonraki birkaç saniye içinde kullanılmazsa tarayıcı konsola uyarı yazıyor. Bu, gereksiz bir şeyi öne aldığınızı gösteriyor.
  • Her şeyi preload ederseniz hiçbir şey öne geçmez. Preload, önceliği diğer kaynaklardan alıyor. Her dosya yüksek öncelikli olursa gerçekten kritik olanlar sırada bekliyor.

Duyarlı (responsive) görsellerde, görsel etiketinin seçeceği dosyanın aynısı seçilsin diye imagesrcset ve imagesizes kullanın. Yoksa preload bir boyutu, <img> başka bir boyutu indirebiliyor:

HTML
<link rel="preload" as="image"
      imagesrcset="/img/kapak-640.webp 640w, /img/kapak-1200.webp 1200w"
      imagesizes="(max-width: 768px) 100vw, 1200px">

prefetch: sonraki sayfa için hazırlık

prefetch ise bu sayfa için değil, kullanıcının büyük ihtimalle gideceği sonraki sayfa için bir ipucu. Tarayıcı dosyayı en düşük öncelikle, ağ boştayken indirip önbelleğe koyuyor:

HTML
<link rel="prefetch" href="/makaleler/sonraki-yazi">

Birkaç adımlı bir formun sonraki adımı, bir serinin sonraki yazısı ya da giriş sayfasından sonra açılan panel için uygun. Tahmininiz tutmazsa indirilen veri boşa gidiyor. Mobil kullanıcıların internet paketini de düşünerek sadece gidilme ihtimali yüksek sayfalar için kullanın. Chromium tabanlı tarayıcılarda bunun daha güçlü bir hâli de var: Speculation Rules API ile sonraki sayfayı sadece indirmek değil, arka planda tamamen hazırlamak (prerender) mümkün.

Dört ipucunun karşılaştırması

İpucuNe yapar?ÖncelikNe için?
dns-prefetchSadece alan adını IP adresine çevirirÇok ucuz, hemenSonra kullanılabilecek üçüncü taraf alan adları
preconnectDNS, TCP ve TLS adımlarını tamamlarHemen; az sayıda kullanılmalıİlk saniyelerde kesin kullanılacak 2–3 kritik alan adı
preloadDosyayı indirirYüksek, bu sayfa içinGeç fark edilen kritik dosyalar: font, kapak görseli
prefetchDosyayı indirip önbelleğe koyarEn düşük, ağ boştaykenSonraki sayfada gerekecek dosyalar

fetchpriority: önceliği doğrudan söylemek

Görsel zaten HTML'de bir <img> etiketiyle duruyorsa tarayıcı onu erkenden görüyor. Bu durumda sorun görselin geç fark edilmesi değil, önceliği olabilir. Tarayıcılar görselleri önce düşük öncelikle istiyor ve hangisinin ekranın üst kısmında kaldığını ancak sayfa düzenini hesapladıktan sonra anlıyor. fetchpriority bu bilgiyi baştan veriyor:

HTML
<!-- Sayfanın en büyük görseli (LCP): yüksek öncelik, lazy yok -->
<img src="/img/kapak.webp" width="1200" height="630" alt="..." fetchpriority="high">

<!-- Kaydırıcının görünmeyen slaytları: düşük öncelik -->
<img src="/img/slayt-2.webp" width="1200" height="630" alt="..." fetchpriority="low">

fetchpriority'yi Chrome, Edge, Safari ve Firefox'un güncel sürümleri destekliyor. Desteklemeyen bir tarayıcı bu özelliği görmezden geliyor, bir şey bozulmuyor. Pratikte şöyle ayırabilirsiniz: görsel HTML'deyse fetchpriority="high" yeterli; CSS ya da JavaScript yüzünden geç fark ediliyorsa preload gerekiyor.

Fontlar: preload ve font-display: swap

Web fontu inene kadar tarayıcılar metni bir süre görünmez tutabiliyor (FOIT, flash of invisible text). Yavaş bir bağlantıda kullanıcı sayfanın iskeletini görüyor ama okuyacak bir şey bulamıyor. font-display: swap, metni hemen yedek fontla göstermeyi ve web fontu gelince değiştirmeyi sağlıyor:

CSS
@font-face {
    font-family: "Inter";
    src: url("/fonts/inter-var.woff2") format("woff2");
    font-weight: 100 900;
    font-display: swap;
}

Google Fonts kullanıyorsanız aynı ayarı adresin sonuna &display=swap ekleyerek yapıyorsunuz. Yalnız swap'ın bir yan etkisi var: font değiştiğinde harf genişlikleri farklıysa satırlar kayıyor ve bu CLS (Cumulative Layout Shift) değerine yansıyor. Bunu azaltmak için:

  • Kritik fontu preload ederek değişimin sayfa ilk görünmeden önce olmasını sağlayın.
  • Yedek fontu size-adjust, ascent-override gibi ayarlarla web fontunun ölçülerine yaklaştırın.
  • Fontun kendisi o kadar önemli değilse font-display: optional kullanın: font kısa sürede gelmezse o sayfa açılışında hiç değiştirilmiyor.
  • Fontu kendi sunucunuzdan sunun. Ayrı bir alan adına bağlanma maliyeti tamamen ortadan kalkıyor.

preload ile lazy loading'in çakışması

Sık rastlanan bir çelişki, aynı görseli hem preload etmek hem de <img> etiketinde loading="lazy" ile işaretlemek. Lazy loading tarayıcıya "bu görsel ekrana yaklaşana kadar bekleyebilir" diyor, preload ise "bunu hemen indir". Sonuçta ya dosya erken inip boşuna bekliyor ya da tarayıcı preload edileni kullanmayıp dosyayı bir daha istiyor. İkisinden birini seçmeniz lazım:

  • Görsel ilk ekranda görünüyorsa kritiktir: loading="lazy" kullanmayın, gerekirse fetchpriority="high" ya da preload ekleyin. Sayfanın en büyük görselini (LCP) lazy yüklemek, LCP süresini uzatmanın en kısa yolu.
  • Görsel aşağıdaysa kritik değildir: loading="lazy" kullanın, preload etmeyin.

Her iki durumda da width ve height değerlerini yazmayı unutmayın. Tarayıcı görselin yerini önceden ayırıyor ve görsel geldiğinde sayfa kaymıyor.

Sık yapılan hatalar ve ölçüm

  • Bütün CSS ve JavaScript dosyalarını preload etmek. HTML'in başında zaten duran dosyalar için preload gereksiz, tarayıcı onları zaten erkenden görüyor.
  • Font preload'unda crossorigin'i, görsel ve font preload'unda as'ı unutmak. İkisi de dosyanın iki kez inmesine yol açıyor.
  • Beş altı farklı alan adına preconnect eklemek. Kullanılmayan bağlantılar kapanıyor ve yapılan iş boşa gidiyor.
  • Kapak görselini lazy yüklemek ya da aynı görseli hem lazy hem preload yapmak.
  • Sonraki sayfa için büyük dosyaları prefetch etmek. Tahmin her tutmadığında mobil kullanıcının internet paketinden boşuna harcanıyor.

Etkisini nasıl ölçersiniz?

Chrome DevTools'ta Network panelini açıp Priority sütununu ekleyin ve şelale (waterfall) görünümüne bakın: kritik font ve kapak görseli HTML'den hemen sonra ve yüksek öncelikle mi başlıyor? Lighthouse ve PageSpeed Insights da LCP görselinin geç fark edildiğini, kullanılmayan preconnect'leri ve görünmeyen metni ayrıca raporluyor. Her değişiklikten sonra tekrar ölçün. Özellikle preload yanlış yerde kullanılınca sayfayı hızlandırmak yerine yavaşlatabiliyor.

Sonuç

Kaynak ipuçları, tarayıcının sizden daha geç öğreneceği şeyleri ona önceden söylemenizi sağlıyor. Sonra kullanılabilecek alan adlarına dns-prefetch, ilk saniyelerde kesin gerekenlere preconnect, geç fark edilen kritik dosyalara preload, sonraki sayfa için de prefetch. HTML'de zaten duran önemli bir görsel için çoğu zaman fetchpriority="high" yeterli. Hepsinde ortak kural, abartmamak: öncelik ancak az sayıda dosyaya verildiğinde işe yarıyor. Sıkıştırma, önbellek ve görsel optimizasyonu gibi diğer konular için Web Sitesi Hızı ve Core Web Vitals yazıma bakabilirsiniz.

Daha ayrıntılı bilgi isterseniz MDN'deki rel=preload, rel=preconnect ve fetchpriority sayfaları ile web.dev'deki kaynak önceliği yazıları iyi bir kaynak.