preload, preconnect ve prefetch, <link> etiketinin rel değerleridir ve tarayıcıya "bunu önceden hazırla" der, ama hazırladıkları şey farklıdır. rel="preload" mevcut sayfanın kısa süre sonra ihtiyaç duyacağı bir dosyayı yüksek öncelikle indirir ve önbelleğe koyar, çalıştırmaz. rel="preconnect" dosya indirmez, yalnızca bir kökene bağlantıyı (DNS, TCP ve HTTPS için TLS) önceden açar. rel="dns-prefetch" yalnızca DNS çözümlemesini yapar. rel="prefetch" ise bir sonraki gezinmede gerekebilecek kaynakları düşük öncelikle indirir. JavaScript modülleri için ayrıca rel="modulepreload" vardır.

Bu yazıda her değerin ne zaman işe yaradığını, zorunlu öznitelikleri (as, crossorigin, type, media), öncelik ipucu veren fetchpriority özniteliğini ve en sık yapılan hataları MDN belgelerine dayanarak anlatıyoruz. Bu ipuçlarının Core Web Vitals ölçümlerine etkisi sayfa hızı ve Core Web Vitals yazısında ele alınıyor.

Beş değerin karşılaştırması

Beş değerin karşılaştırması: preload, modulepreload, preconnect, dns-prefetch
rel değeriNe yaparHangi gezinme içinÖncelik
preloadDosyayı indirir ve önbelleğe koyar, çalıştırmazMevcut sayfaas türüne göre, yüksek
modulepreloadModülü indirir, ayrıştırır, derler, modül haritasına koyarMevcut sayfaModül betiği gibi
preconnectDNS + TCP (+ TLS) bağlantısını açarBaşka kökenden gelecek isteklerDosya indirmez
dns-prefetchYalnızca DNS çözümlemesiBaşka kökenden gelecek isteklerDosya indirmez
prefetchDosyayı düşük öncelikle indirip HTTP önbelleğine koyarSonraki gezinmeDüşük

rel="preload": mevcut sayfa için erken indirme

preload, head içinde bir indirme isteğini önceden bildirmenizi sağlar. Tarayıcının ana çizim mekanizması devreye girmeden önce kaynak indirilmeye başlar; böylece gerektiğinde hazırdır ve çizimi engelleme olasılığı azalır. MDN'in vurguladığı gibi, adında "load" geçse de preload betiği yükleyip çalıştırmaz, yalnızca yüksek öncelikle indirilip önbelleğe alınmasını planlar. Kaynağı gerçekten kullanmak için yine normal etiketi (<link rel="stylesheet">, <script>, <img>) yazmanız gerekir.

İki öznitelik zorunludur: href kaynağın yolu, as kaynağın türüdür. as değeri sayesinde tarayıcı kaynağı doğru şekilde önbelleğe alıp sonraki isteklerde yeniden kullanabilir, doğru içerik güvenlik politikasını uygular, doğru Accept başlığını gönderir ve isteğin önceliğini belirler. rel="preload" için MDN'in listelediği as değerleri şunlardır:

as değeriKaynak türüNot
fetchfetch veya XHR ile alınacak kaynak: ArrayBuffer, WebAssembly, JSONcrossorigin gerekir
fontYazı tipi dosyası (CSS @font-face)crossorigin gerekir
imageGörsel dosyası (img, picture, CSS görselleri)
scriptJavaScript dosyasıModüller için modulepreload
styleCSS stil sayfası
trackWebVTT altyazı dosyası
html
<head>
  <meta charset="utf-8" />
  <title>Preload örneği</title>
  <link rel="preload" href="css/ana.css" as="style" />
  <link rel="preload" href="js/ana.js" as="script" />
  <link rel="stylesheet" href="css/ana.css" />
</head>
<body>
  <h1>Kampanyalar</h1>
  <script src="js/ana.js" defer></script>
</body>

MDN bu örneğin basit olduğunu kabul eder: tarayıcı aynı HTML parçasında <link rel="stylesheet"> ve <script> öğelerini zaten görür, kazanç azdır. preload'un asıl faydası geç keşfedilen ve büyük kaynaklarda ortaya çıkar: CSS dosyasının içinden çağrılan yazı tipleri ve arka plan görselleri, JavaScript'in sonradan istediği betikler gibi. Tarayıcı bunları ancak CSS'i ya da betiği indirip ayrıştırdıktan sonra fark eder; preload bu bekleme süresini ortadan kaldırır.

Yazı tipleri ve crossorigin

font ve fetch türündeki önyüklemelerde crossorigin özniteliği şarttır. MDN'e göre bu öznitelik, istek aynı kökenden olsa bile kaynağın sonradan yapılacak gerçek isteğinin CORS ve kimlik bilgisi moduyla eşleşmelidir. Yazı tipleri anonim modda CORS ile alındığı için önyükleme de crossorigin taşımalıdır; yoksa önyüklenen dosya ile CSS'in istediği dosya eşleşmez ve yazı tipi ikinci kez indirilebilir.

html
<link rel="preload" href="fonts/govde.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="fonts/baslik.woff2" as="font" type="font/woff2" crossorigin />
<link rel="stylesheet" href="css/ana.css" />

type ile desteklenmeyen biçimleri atlamak

type özniteliğine kaynağın MIME türünü yazdığınızda tarayıcı o türü destekleyip desteklemediğine bakar ve yalnızca destekliyorsa indirir. Bu, AVIF gibi yeni görsel biçimlerinde işe yarar. MDN önemli bir uyarı da ekler: aynı görselin hem AVIF hem WebP sürümü için önyükleme yazarsanız ikisini de destekleyen tarayıcılar ikisini de indirir, oysa yalnızca biri kullanılır. Bu yüzden yalnızca kullanıcılarınızın çoğunun gerçekten kullanacağı biçimi önyükleyin; diğer biçim yine çalışır, yalnızca önyüklenmez.

html
<head>
  <link rel="preload" href="img/kapak.avif" as="image" type="image/avif" />
</head>
<body>
  <picture>
    <source srcset="img/kapak.avif" type="image/avif" />
    <source srcset="img/kapak.webp" type="image/webp" />
    <img src="img/kapak.jpg" alt="Kampanya kapak görseli" width="1200" height="600" />
  </picture>
</body>

<picture> ve <source> öğelerinin kendisi picture ve source yazısında anlatılıyor.

media ile duyarlı önyükleme

media özniteliği bir medya sorgusu alır ve önyüklemeyi koşula bağlar. Dar ekranda dar görselin, geniş ekranda geniş görselin önyüklenmesini sağlayabilirsiniz. MDN aynı tekniğin yazı tiplerinde de işe yaradığını, yazı tipinin çizim anında hazır olma ihtimalini artırarak biçimlenmemiş metnin bir an görünmesini (FOUT) azalttığını belirtir.

html
<link rel="preload" href="img/arka-dar.png" as="image" media="(width <= 600px)" />
<link rel="preload" href="img/arka-genis.png" as="image" media="(width > 600px)" />

Görseli bir <img srcset> seçecekse imagesrcset ve imagesizes öznitelikleri kullanılır. Bunlar yalnızca rel="preload" ve as="image" ile geçerlidir ve sözdizimleri <img> öğesinin srcset ve sizes öznitelikleriyle aynıdır. Değerleri görseldekiyle birebir aynı yazmanız gerekir ki tarayıcı aynı dosyayı seçsin. srcset ve sizes'ın optimizasyon açısından kullanımı görsel optimizasyonu yazısında, öznitelikleri img etiketi yazısında anlatılıyor.

html
<link rel="preload" as="image" href="img/hero-800.jpg"
      imagesrcset="img/hero-400.jpg 400w, img/hero-800.jpg 800w"
      imagesizes="100vw" />
<img src="img/hero-800.jpg"
     srcset="img/hero-400.jpg 400w, img/hero-800.jpg 800w"
     sizes="100vw" alt="Ofisimizin girişi" width="800" height="450" />

Betikle önyükleme

Önyükleme betikle de başlatılabilir: bir link öğesi oluşturup rel, as ve href değerlerini verip head'e eklersiniz. Dosya indirilir ama kullanılmaz; çalıştırmak için daha sonra bir script öğesi oluşturup aynı adresi verirsiniz. Bu, bir betiği önceden indirip çalıştırmayı tam gerektiği ana ertelemek için kullanışlıdır.

javascript
const onYukle = document.createElement("link");
onYukle.href = "/js/grafik.js";
onYukle.rel = "preload";
onYukle.as = "script";
document.head.appendChild(onYukle);

rel="modulepreload": JavaScript modülleri için

rel="modulepreload": JavaScript modülleri için: modulepreload isteğinin modu her zaman cors'tur. crossorigin yalnızca kimlik..., as isteğe bağlıdır ve varsayılanı script'tir...

JavaScript modülleriyle çalışıyorsanız MDN preload yerine modulepreload kullanmanızı söyler. Fark şudur: preload dosyayı yalnızca indirip önbelleğe koyar; modulepreload modülü indirir, ayrıştırır, derler ve belgenin modül haritasına koyar, böylece çalışmaya hazır olur. Normalde tarayıcı ana modülü indirip ayrıştırdıktan sonra onun içe aktardığı modülleri fark eder ve sırayla indirir; modulepreload ile hepsi paralel inmeye başlar.

html
<!doctype html>
<html lang="tr">
  <head>
    <meta charset="utf-8" />
    <title>Modül önyükleme</title>
    <link rel="modulepreload" href="js/ana.js" />
    <link rel="modulepreload" href="js/moduller/tuval.js" />
    <link rel="modulepreload" href="js/moduller/kare.js" />
    <script type="module" src="js/ana.js"></script>
  </head>
  <body></body>
</html>
  • modulepreload isteğinin modu her zaman cors'tur. crossorigin yalnızca kimlik bilgisi modunu belirler: yazılmazsa ya da anonymous ise çerezler yalnızca aynı kökene, use-credentials ise her isteğe gönderilir.
  • as isteğe bağlıdır ve varsayılanı script'tir. style, json, text ve worker, serviceworker, sharedworker, audioworklet, paintworklet gibi betik benzeri hedefler de verilebilir; başka bir hedef verilirse öğede error olayı tetiklenir.
  • Tarayıcı modülün bağımlılıklarını kendiliğinden de indirebilir, ama bu tarayıcıya özgü bir iyileştirmedir. Tüm tarayıcıların bağımlılıkları önyüklemesini garanti etmenin tek yolu her birini ayrı ayrı yazmaktır.
  • load ve error olayları yalnızca açıkça belirtilen kaynak için tetiklenir; kendiliğinden indirilen bağımlılıklar için ek olay gelmez.

MDN her şeyi önyüklemeye çalışmamanızı da hatırlatır: önyüklediğiniz her şey başka işlemlerin kaynaklarından çalar ve kullanıcı deneyimini kötüleştirebilir. Modül betiklerinin genel davranışı script etiketi yazısında, import map ile modül adlandırma importmap yazısında anlatılıyor.

rel="preconnect" ve rel="dns-prefetch"

preconnect, kullanıcının bir kökenden kaynak isteyeceğini tarayıcıya önceden söyler; tarayıcı da o kökene bağlantıyı önceden açar. HTTP kökenleri için DNS ve TCP, HTTPS kökenleri için DNS, TCP ve TLS el sıkışmasının bir kısmı ya da tamamı önceden yapılır. Hiçbir içerik indirilmez ve özel bilgi açığa çıkmaz. Kazanç başka kökene yapılan her türlü istekte (gezinme veya alt kaynak) görülür; aynı kökene yapılan isteklerde fayda yoktur, çünkü bağlantı zaten açıktır.

html
<link rel="preconnect" href="https://cdn.ornek.com" />
<link rel="dns-prefetch" href="https://analiz.ornek.net" />

MDN'in önemli uyarısı: sayfa çok sayıda üçüncü taraf alan adına bağlanıyorsa hepsine preconnect yazmak ters etki yapabilir. preconnect'i yalnızca en kritik bağlantılar için kullanın; diğerleri için ilk adım olan DNS sorgusunu kazandıran dns-prefetch yeterlidir. dns-prefetch head ve body içindeki <link> öğelerinde kullanılabilir. MDN'in hızlı sayfa yazımı rehberi de aynı yöne işaret eder: her ayrı alan adı bir DNS sorgusu maliyeti getirir, bu yüzden sayfadaki farklı alan adı sayısını mümkün olduğunca az tutun.

preconnect HTTP Link başlığıyla da verilebilir: Link: <https://cdn.ornek.com>; rel="preconnect". HTML'e erişiminiz olmayan durumlarda sunucu tarafında bu yolu kullanabilirsiniz.

rel="prefetch": bir sonraki sayfa için

rel="prefetch": bir sonraki sayfa için: prefetch, MDN'e göre priority, İstek Sec-Purpose, Cache-Control başlıklarına dikkat edin, Birçok tarayıcı önbellek bölümlemesi (cache...

prefetch, kullanıcının sonraki gezinmelerde ihtiyaç duyacağı kaynakları önceden indirip önbelleğe almak içindir ve aynı siteye ait gezinme kaynakları ya da aynı sitenin sayfalarında kullanılan alt kaynaklar için kullanılır. Sonuç diskteki HTTP önbelleğinde tutulur; bu yüzden mevcut sayfada kullanılmasa bile alt kaynaklar için faydalıdır. Örneğin bir açılış sayfası, sitenin geri kalanında kullanılan ağır stil dosyasını önceden alabilir.

html
<link rel="prefetch" href="app/stil.css" />
<link rel="prefetch" href="kayit-ol" />
  • prefetch, MDN'e göre priority: "low" seçeneğiyle yapılmış bir fetch() çağrısına işlevsel olarak eşdeğerdir, ama genellikle daha da düşük öncelik alır. Tarayıcılar genel olarak prefetch'e preload'dan daha düşük öncelik verir: mevcut sayfa bir sonrakinden önemlidir.
  • İstek Sec-Purpose: prefetch başlığını taşır; sunucu bu başlığa bakarak önbellek sürelerini değiştirebilir. Sec-Fetch-Dest başlığının değeri empty olur, Accept başlığı ise normal gezinme isteğindekiyle aynıdır.
  • Cache-Control başlıklarına dikkat edin: no-cache veya no-store önceden indirmeyi engelleyebilir.
  • Birçok tarayıcı önbellek bölümlemesi (cache partitioning) uygular. Bu yüzden farklı bir üst düzey site için yapılan prefetch işe yaramaz: https://haber.ornek/makale için yapılan önceden indirme https://toplayici.ornek/ üzerinden kullanılamaz.

Bu sınırlamalar nedeniyle MDN, belge (sayfa) önceden indirmeleri için destekleyen tarayıcılarda Speculation Rules API'nin kullanılmasını önerir. Eski rel="prerender" değeri de bu API ile yerini bırakmıştır. Kurallar <script type="speculationrules"> içinde JSON olarak yazılır; prefetch yalnızca belgenin yanıt gövdesini indirir, prerender ise sayfayı alt kaynaklarıyla birlikte görünmez bir sekmede tamamen yükleyip çizer. Bu yeni bir özelliktir; tarayıcı desteği için MDN uyumluluk tablosuna bakın. Living Standard'a eklenen diğer yenilikler yeni HTML özellikleri yazısında özetleniyor.

html
<script type="speculationrules">
  {
    "prefetch": [
      { "urls": ["/sepet", "/odeme"] }
    ],
    "prerender": [
      { "where": { "selector_matches": ".urun-baglantisi" }, "eagerness": "conservative" }
    ]
  }
</script>

fetchpriority: öncelik ipucu

fetchpriority özniteliği <img>, <link> ve <script> öğelerinde kullanılır ve tarayıcıya bir kaynağın aynı türdeki diğer kaynaklara göre daha yüksek ya da daha düşük öncelikle alınması gerektiğini söyler. Değerleri high, low ve auto'dur; auto varsayılandır ve değer verilmezse ya da geçersizse kullanılır. Öncelik bir ipucudur: hem iç öncelikler hem de bu özniteliğin etkisi tamamen tarayıcıya bağlıdır.

MDN'in örneği şöyledir: bir görselin Largest Contentful Paint (LCP) ölçümüne büyük katkı yaptığını biliyorsanız onun için <link rel="preload"> yazıp önceliğini fetchpriority="high" ile daha da yükseltebilirsiniz. Tersine, sayfanın altındaki ikincil bir betiğe fetchpriority="low" verebilirsiniz.

html
<link rel="preload" href="img/manset.jpg" as="image" fetchpriority="high" />
<img src="img/manset.jpg" alt="Kış kampanyası afişi" width="1200" height="500" fetchpriority="high" />
<script src="js/yorumlar.js" defer fetchpriority="low"></script>

Sık yapılan hatalar

  • as yazmamak: rel="preload" için as zorunludur; yoksa tarayıcı türü bilemez, önceliği, CSP'yi ve önbellek eşleşmesini doğru kuramaz.
  • Yazı tipinde crossorigin unutmak: font ve fetch önyüklemelerinde gerekir; aksi hâlde istekler eşleşmeyebilir.
  • preload'un betiği çalıştıracağını sanmak: yalnızca indirir; normal <script> etiketi yine gerekir.
  • Aynı görselin her biçimini önyüklemek: destekleyen tarayıcı hepsini indirir; yalnızca çoğunluğun kullanacağı biçimi önyükleyin.
  • Her alan adına preconnect yazmak: çok sayıda bağlantı ters etki yapabilir; kritik olmayanlarda dns-prefetch yeterlidir.
  • Aynı kökene preconnect yazmak: bağlantı zaten açık olduğu için faydası yoktur.
  • Modüller için preload kullanmak: MDN modüller için modulepreload önerir.
  • Her şeyi önyüklemek: önyüklenen her kaynak başka işlerin kaynaklarından çalar.

Sık Sorulan Sorular

preload ile prefetch arasındaki fark nedir?

preload mevcut sayfanın kısa süre içinde kullanacağı kaynak içindir ve yüksek öncelikle indirilir; as zorunludur. prefetch sonraki gezinmede gerekebilecek kaynak içindir, düşük öncelikle indirilir ve HTTP önbelleğinde bekler.

preconnect mi dns-prefetch mi?

En kritik bir iki üçüncü taraf kökeni için preconnect, geri kalanlar için dns-prefetch. preconnect DNS'e ek olarak TCP ve TLS adımlarını da önceden yapar, bu yüzden daha pahalıdır.

Kullanılmayan bir preload sorun yaratır mı?

Dosya boşuna indirilir ve o sırada başka kaynakların bant genişliğini ve önceliğini paylaşır. MDN, önyüklenecek kaynakların diğer işlemlerle dengelenmesi gerektiğini vurgular. Gerçekten kullanmadığınız önyüklemeleri kaldırın.

Bu ipuçlarını HTML dışında verebilir miyim?

Evet, preconnect gibi ipuçları HTTP Link yanıt başlığıyla da verilebilir. Speculation rules için de Speculation-Rules HTTP başlığıyla harici bir dosya gösterilebilir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: HTML öğrenme rehberi · link etiketi ve rel değerleri · script etiketi · img etiketi · integrity ve crossorigin · Core Web Vitals · görsel optimizasyonu