İçeriğe geç
academia.sh

Ders 04 / 25

Kaynak Yükleme Sırası

Betik ve biçem dosyalarının ayrıştırmayı ve çizimi nasıl beklettiği; erteleme ve eşzamansız yükleme kiplerinin bir olay çizelgesi üzerinden karşılaştırılması.

İçindekiler

Önceki ders ağacın sözcük birimi akışından kesintisiz kurulduğunu varsaydı. Gerçek belgeler bu varsayımı bozar: ayrıştırma sürerken belge kendisinden başka kaynaklara başvurur ve bu başvuruların bir bölümü ayrıştırmayı durdurur.

İnternet Nasıl Çalışır kursundaki Tarayıcı Ne Yapar dersi bu alt kaynak isteklerinin varlığını göstermişti: bir adres yazıldığında sunucu birden çok istek görüyordu. Bu ders, o isteklerin ne zaman yapıldığını ve belgenin işlenmesini nasıl etkilediğini ele alır. Konu bir başarım ayrıntısı değil, belgenin nasıl yazılacağını belirleyen bir kısıttır.

Başvuru Ayrıştırma Sırasında Doğar

Tarayıcı belgeyi baştan sona okur. link ögesini gördüğü anda biçem dosyasının isteğini yollar, img ögesini gördüğü anda görselin isteğini yollar. Belgenin sonunu beklemez. Bunun doğrudan sonucu şudur: bir kaynağın belgedeki yeri, istendiği anı belirler. Belgenin sonuna yazılan bir biçem dosyası, başına yazılana göre daha geç istenir.

Kaynakların ayrıştırma üzerindeki etkisi aynı değildir. Üç davranış vardır.

Kaynak Ayrıştırmayı durdurur Çizimi bekletir
Görsel Hayır Hayır
Biçem dosyası (link rel="stylesheet") Hayır Evet
Betik (öznitelik yazılmamış) Evet Dolaylı olarak
Betik (defer) Hayır Hayır
Betik (async) Yürütülürken Dolaylı olarak

Betik Ayrıştırmayı Neden Durdurur

Öznitelik yazılmamış bir betik ögesi görüldüğünde ayrıştırma durur, betik indirilir, yürütülür ve ancak sonra ayrıştırmaya devam edilir. Bu davranış bir eksiklik değil, bir zorunluluktur: betik, o ana kadar kurulmuş ağacı okuyabilir ve ona düğüm ekleyebilir. Ayrıştırıcı aynı anda çalışsaydı, betiğin gördüğü ağaç ile ayrıştırıcının kurduğu ağaç çakışırdı.

Bu zorunluluğun bedeli, betik indirilirken belgenin geri kalanının işlenmemesidir. Bedeli ödememenin iki yolu vardır ve ikisi de betiğin ağaca ne zaman erişeceğine ilişkin bir söz verir.

Erteleme (defer): betik ayrıştırmayı durdurmadan indirilir, ayrıştırma bittikten sonra yürütülür. Birden çok ertelenmiş betik, belgedeki yazılış sırasına göre yürütülür. Bu, birbirine bağımlı betikler için tek güvenli kiptir.

Eşzamansız (async): betik ayrıştırmayı durdurmadan indirilir ve indiği anda yürütülür; yürütme sırasında ayrıştırma durur. Yürütme sırası indirme sırasına bağlıdır, belgedeki sıraya değil. Başka betiklere bağımlı olmayan, tek başına çalışan betikler içindir.

Bu ayrım bir tercih değil, bir sözleşmedir: async yazmak “sıramın bir önemi yok” demektir. Sırası önemli olan bir betiğe bu öznitelik yazılırsa, hata belirli koşullarda ortaya çıkar ve yeniden üretilmesi güçtür.

Biçem Dosyası Neden Çizimi Bekletir

Biçem dosyası ayrıştırmayı durdurmaz — ağaç kurulmayı sürdürür. Ancak biçem hesabı tamamlanmadan çizim yapılamaz; yapılsaydı sayfa önce biçemsiz görünür, sonra biçemli görünüme atlardı. Tarayıcı bunun yerine bekler.

İkinci ve daha az bilinen bir kural daha vardır: bekleyen bir biçem dosyası varken betik yürütülmez. Gerekçesi aynı türdendir. Betik, bir ögenin hesaplanmış biçem değerini sorabilir; henüz uygulanmamış bir kural varsa alacağı yanıt yanlış olur. Bu nedenle betik, kendisi inmiş olsa bile biçem dosyası inene kadar bekletilir.

Olay Çizelgesi

Aşağıdaki betik bu kuralları bir olay modeli olarak çalıştırır. Gerçek bir tarayıcı değil, kuralların modelidir: her belge parçası bir birim ayrıştırma süresi tutar, her kaynağın getirme süresi verilidir.

// yukleme.mjs — ayristirma-yukleme kurallarinin olay modeli
const belge = [
  { tur: "isaretleme", ad: "head baslangici", sure: 1 },
  { tur: "kaynak", ad: "bicem.css", bicim: "bicem", getirme: 6 },
  { tur: "isaretleme", ad: "govde ilk yarisi", sure: 2 },
  { tur: "kaynak", ad: "olcum.js", bicim: "betik", kip: "engelleyen", getirme: 3, yurutme: 1 },
  { tur: "isaretleme", ad: "govde ikinci yarisi", sure: 2 },
  { tur: "kaynak", ad: "grafik.js", bicim: "betik", kip: "ertelenen", getirme: 5, yurutme: 1 },
  { tur: "isaretleme", ad: "govde sonu", sure: 1 },
];

const gunluk = [];
let saat = 0;
const ertelenenler = [];
let bicemHazir = Infinity;

for (const parca of belge) {
  if (parca.tur === "isaretleme") {
    gunluk.push([saat, saat + parca.sure, "ayristirma: " + parca.ad]);
    saat += parca.sure;
    continue;
  }
  if (parca.bicim === "bicem") {
    gunluk.push([saat, saat, "istek: " + parca.ad + " (arka planda)"]);
    bicemHazir = saat + parca.getirme;
    continue;
  }
  if (parca.kip === "engelleyen") {
    const getirmeBitis = saat + parca.getirme;
    const yurutmeBaslangic = Math.max(getirmeBitis, bicemHazir);
    gunluk.push([saat, getirmeBitis, "DURDU: " + parca.ad + " getiriliyor"]);
    if (yurutmeBaslangic > getirmeBitis) {
      gunluk.push([getirmeBitis, yurutmeBaslangic, "DURDU: bekleyen bicem"]);
    }
    gunluk.push([yurutmeBaslangic, yurutmeBaslangic + parca.yurutme, "yurutme: " + parca.ad]);
    saat = yurutmeBaslangic + parca.yurutme;
    continue;
  }
  if (parca.kip === "ertelenen") {
    gunluk.push([saat, saat, "istek: " + parca.ad + " (arka planda)"]);
    ertelenenler.push({ ...parca, hazir: saat + parca.getirme });
  }
}

const ayristirmaBitis = saat;
gunluk.push([saat, saat, "ayristirma tamamlandi"]);
for (const betik of ertelenenler) {
  const baslangic = Math.max(saat, betik.hazir);
  gunluk.push([baslangic, baslangic + betik.yurutme, "yurutme (ertelenen): " + betik.ad]);
  saat = baslangic + betik.yurutme;
}

for (const [bas, bit, ad] of gunluk) {
  console.log(String(bas).padStart(3) + " - " + String(bit).padStart(3) + "  " + ad);
}
console.log("ayristirma bitisi:", ayristirmaBitis, "| tum betikler bitti:", saat);
  0 -   1  ayristirma: head baslangici
  1 -   1  istek: bicem.css (arka planda)
  1 -   3  ayristirma: govde ilk yarisi
  3 -   6  DURDU: olcum.js getiriliyor
  6 -   7  DURDU: bekleyen bicem
  7 -   8  yurutme: olcum.js
  8 -  10  ayristirma: govde ikinci yarisi
 10 -  10  istek: grafik.js (arka planda)
 10 -  11  ayristirma: govde sonu
 11 -  11  ayristirma tamamlandi
 15 -  16  yurutme (ertelenen): grafik.js
ayristirma bitisi: 11 | tum betikler bitti: 16

Çizelge üç şeyi görünür kılar. Birincisi, olcum.js üç birim boyunca ayrıştırmayı durdurmuştur (3–6 aralığı) ve indikten sonra bile bir birim daha beklemiştir; beklediği şey bicem.css dosyasının hazır olmasıdır. İkincisi, grafik.js ertelenmiş olduğu için ayrıştırmayı hiç durdurmamış, isteği 10. birimde çıkmış ve ayrıştırma bittikten sonra yürütülmüştür. Üçüncüsü, ayrıştırmanın bitişi (11) ile betiklerin bitişi (16) ayrı büyüklüklerdir; belge okunabilir duruma geldiğinde tüm davranış katmanı henüz hazır olmayabilir.

Sayılar bu modelin varsayımlarıdır; gerçek süreler ağ koşullarına ve dosya boyutlarına bağlıdır. Değişmeyen şey sıralamadır.

Yerleştirme Kararları

Kurallar birkaç doğrudan sonuca varır.

Biçem dosyası belgenin baş bölümüne yazılır. Geç istenirse çizim geç başlar; gövdenin ortasına yazılırsa, o noktaya kadar çizilmiş içerik sonradan yeniden biçemlenir.

Ayrıştırmayı durdurmayan bir betik kipi, öznitelik yazılmamış betiğe yeğlenir. Belgenin sonuna yazmak da ayrıştırmanın büyük bölümünü kurtarır ancak erteleme kadar erken indirme başlatmaz: sona yazılan betiğin isteği ancak ayrıştırıcı oraya vardığında çıkar.

Ayrıştırıcı durduğunda tarayıcı boş oturmaz. Belgenin ileri bölümlerini yalnızca kaynak başvurusu aramak için önden tarayan bir düzenek, bulduğu istekleri erkenden yollar. Bu davranış, kaynakların belgede açıkça bildirilmiş olmasına dayanır: adresi bir betiğin hesaplayarak ürettiği bir kaynak bu taramada görünmez.

Özet

  • Kaynak istekleri ayrıştırma sırasında doğar; bir kaynağın belgedeki yeri, istendiği anı belirler.
  • Öznitelik yazılmamış betik ayrıştırmayı durdurur, çünkü betik o ana kadar kurulmuş ağacı okuyabilir ve değiştirebilir.
  • Erteleme, betiği ayrıştırma bittikten sonra ve belgedeki sırayla yürütür; eşzamansız kip indiği anda yürütür ve sıra vermez.
  • Biçem dosyası ayrıştırmayı durdurmaz ama çizimi bekletir; ayrıca bekleyen biçem varken betik yürütülmez.
  • Ayrıştırmanın bitişi ile betiklerin bitişi ayrı anlardır; belgenin okunabilir olması tüm davranışın hazır olması demek değildir.

Sonraki Adım

Bu konu, belgenin nasıl işlendiğini kurdu: baytların ağaca çevrilmesi, ağacın kutulara dönüşmesi, kaynakların bu zincire etkisi. Sonraki konu belgenin kendisini yazmaya başlar. İlk soru, her belgenin en dışındaki yapıdır: belge türü bildiriminin ne işe yaradığı, baş ve gövde bölümlerinin ne ayırdığı ve bunların hiçbiri yazılmadığında ayrıştırıcının ne kurduğu.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat