Koddan Görüntüye: Tarayıcı Nasıl Çalışır?
Bu bölümde, bir web sayfasının tarayıcı içerisinde nasıl işlendiğini
adım adım inceleyeceksin.
HTML parsing, CSS hesaplama ve render sürecini analiz ederek
tarayıcı motorunun iç mekanizmasını simüle edeceksin.
Tarayıcı Motoru Gerçekte Ne Yapar? İstek → Parse → Render
Bir web sayfası açtığında gördüğün şey, aslında uzun bir işlemin son adımıdır.
Tarayıcı, sadece HTML dosyasını göstermez; bu dosyayı analiz eder, işler ve ekrana çizer.
Bu süreç, tek bir işlem değil; birden fazla aşamadan oluşan bir pipeline’dır.
Bu nedenle tarayıcı, kodu doğrudan göstermez; önce anlamlandırır, sonra üretir.
3 Ana AşamaTarayıcı motorunun çalışma süreci üç temel aşamadan oluşur.
İlk olarak, HTML ve diğer kaynaklar yüklenir.
Daha sonra bu veriler parse edilerek anlamlı yapılara dönüştürülür.
Son aşamada ise bu yapılar ekrana çizilir.
Bu süreç: yükleme → analiz → render olarak özetlenebilir.
Parsing MantığıTarayıcı, gelen HTML kodunu doğrudan kullanmaz.
Önce bu kodu parçalar, etiketleri analiz eder ve bir yapı oluşturur.
Bu yapı sayesinde, sayfanın içeriği anlamlandırılır.
Aynı şekilde CSS de analiz edilir ve görsel kurallar belirlenir.
Render MantığıTarayıcı, oluşturduğu yapıları doğrudan ekrana çizmez.
Önce bu yapıların nasıl görüneceğini hesaplar.
Boyutlar, konumlar ve stiller belirlenir.
Daha sonra bu bilgiler kullanılarak piksel bazlı bir çıktı oluşturulur.
İşte gördüğün sayfa, bu hesaplamaların sonucudur.
Neden Önemli?Tarayıcı motorunu anlamak, sadece frontend geliştirme için değil; performans ve optimizasyon için de kritik öneme sahiptir.
Bir sayfanın neden yavaş yüklendiğini ya da neden yanlış göründüğünü anlamanın yolu, bu süreci bilmektir.
Bu nedenle bu bölümde, sadece sonucu değil; o sonuca giden tüm süreci simüle edeceksin.
HTML Nasıl Parse Edilir? (DOM Oluşumu) Token → Node → Tree
Tarayıcıya ulaşan HTML dosyası, ilk bakışta sadece düz bir metin gibi görünür.
Ancak tarayıcı bu metni olduğu gibi kullanmaz. Çünkü metin tek başına bir anlam ifade etmez; sadece karakterlerden oluşan bir akıştır.
Bu nedenle tarayıcı, bu karakter akışını anlamlı bir yapıya dönüştürmek zorundadır.
İşte bu dönüşüm süreci, HTML parsing olarak adlandırılır.
Bu süreç sonunda ortaya çıkan yapı ise DOM (Document Object Model) olarak bilinir.
1. Tokenization (Parçalama)Parsing sürecinin ilk adımı, HTML metninin küçük parçalara ayrılmasıdır.
Tarayıcı, gelen HTML’i karakter karakter okur ve bu karakterleri anlamlı parçalara böler.
Bu parçalar “token” olarak adlandırılır.
Örneğin bir açılış etiketi, kapanış etiketi veya metin içeriği ayrı ayrı token’lara dönüştürülür.
Bu aşamada tarayıcı artık düz metinle değil, anlamlı birimlerle çalışmaya başlar.
2. Node OluşumuOluşturulan her token, bir sonraki aşamada node adı verilen yapılara dönüştürülür.
Bir node, DOM ağacının temel yapı taşıdır.
Örneğin bir HTML etiketi, bir element node oluşturur.
Metin içerikleri ise text node olarak temsil edilir.
Bu aşamada tarayıcı artık sadece parçaları değil, bu parçaların temsil ettiği yapıları üretir.
3. DOM Ağacı OluşumuNode’lar oluşturulduktan sonra, bu node’lar birbirine bağlanarak bir ağaç yapısı oluşturur.
Bu yapı, DOM ağacı olarak adlandırılır.
DOM yapısında her node, bir parent (üst) ve child (alt) ilişkisine sahiptir.
Bu sayede HTML içerisindeki iç içe yapı, birebir şekilde temsil edilir.
Örneğin bir div içerisinde bulunan bir p etiketi, DOM ağacında da div’in child’ı olarak yer alır.
Bu yapı sayesinde tarayıcı, sayfanın hiyerarşisini ve ilişkilerini anlayabilir.
Streaming ve Anlık OluşumHTML parsing süreci, tüm dosya indirildikten sonra başlamaz.
Tarayıcı, veri geldikçe parsing yapar.
Yani DOM ağacı, parça parça ve anlık olarak oluşur.
Bu sayede sayfa, tamamen yüklenmeden önce bile kısmen görüntülenebilir.
Bu davranış, performans açısından oldukça kritiktir.
Neden Bu Süreç Kritik?DOM ağacı, tarayıcının tüm işlemlerinin merkezinde yer alır.
CSS uygulamaları, JavaScript etkileşimleri ve render süreci bu yapı üzerinden gerçekleşir.
Bu nedenle DOM, sadece bir veri yapısı değil; tarayıcının çalışma temelidir.
Bu süreci anlamak, performans problemlerini çözmekten doğru yapı kurmaya kadar birçok konuda kritik avantaj sağlar.
HTML Parser Simülasyonu: Metinden DOM Ağacına Simülasyon Modeli
Şimdiye kadar HTML parsing sürecini teorik olarak inceledik. Ancak bu süreci gerçekten anlamanın yolu, onu adım adım yeniden inşa etmektir.
Bu noktada artık sadece “tarayıcı ne yapar?” sorusunu değil; “bu süreç içeride nasıl işler?” sorusunu cevaplayacağız.
Bu simülasyon, gerçek bir tarayıcı motorunun birebir kopyası değildir; ancak onun çalışma mantığını modelleyen sadeleştirilmiş bir sistemdir.
Simülasyonun AmacıBu simülasyondaki temel amaç, HTML metninin nasıl bir veri yapısına dönüştüğünü anlamaktır.
Tarayıcı, gelen HTML’i doğrudan kullanmaz; onu analiz eder, parçalar ve bir yapı haline getirir.
Biz de bu süreçte, HTML → DOM dönüşümünü adım adım modelleyeceğiz.
Nasıl Çalışacak?Simülasyon sürecinde HTML metni, karakter karakter okunacaktır.
Açılış ve kapanış etiketleri tespit edilecek, metin içerikleri ayrıştırılacaktır.
Bu bilgiler kullanılarak, her biri bir node olacak şekilde yeni yapılar üretilecektir.
Son aşamada bu node’lar, bir ağaç yapısı içerisinde birbirine bağlanacaktır.
Dikkat Edilmesi Gereken KavramlarBu simülasyonu takip ederken, aşağıdaki temel kavramlara odaklanman önemlidir:
- Token: HTML’in anlamlı parçalara ayrılması
- Stack: Açılan ve kapanan yapıların takibi
- Node: DOM ağacının temel birimi
- Tree: Node’ların hiyerarşik organizasyonu
Bu kavramlar birlikte çalışarak, düz metni anlamlı bir yapıya dönüştürür.
SonuçAşağıdaki algoritma, HTML parsing sürecinin sadeleştirilmiş bir modelidir.
Bu modeli anlamak, tarayıcının nasıl çalıştığını kavramanın en önemli adımlarından biridir.
Artık hazırız: HTML → DOM dönüşümünü adım adım inceleyeceğiz.
HTML Parser simülasyonu
Bu simülasyonda HTML metni, karakter karakter okunarak analiz edilir.
- HTML metni token’lara ayrılır
- Açılış ve kapanış etiketleri tespit edilir
- Stack ile iç içe yapı kontrol edilir
- Her yapı bir node olarak oluşturulur
- Node’lar bir DOM ağacı halinde bağlanır
// HTML Parser Simülasyonu
// Amaç: HTML string → Token → Node → DOM Tree
function parseHTML(html) {
let index = 0;
const root = {
type: "root",
children: []
};
const stack = [root];
while (index < html.length) {
// 1. TAG BAŞLANGICI
if (html[index] === "<") {
// Closing tag
if (html[index + 1] === "/") {
index += 2;
let closingTag = "";
while (html[index] !== ">") {
closingTag += html[index];
index++;
}
index++; // >
// stack'ten çık (node kapandı)
stack.pop();
} else {
// Opening tag
index++;
let tagName = "";
while (html[index] !== ">" && html[index] !== " ") {
tagName += html[index];
index++;
}
// Basit attribute skip (advanced değil)
while (html[index] !== ">") {
index++;
}
index++; // >
const elementNode = {
type: "element",
tag: tagName,
children: []
};
// parent'a ekle
const parent = stack[stack.length - 1];
parent.children.push(elementNode);
// stack'e ekle
stack.push(elementNode);
}
} else {
// 2. TEXT NODE
let text = "";
while (index < html.length && html[index] !== "<") {
text += html[index];
index++;
}
text = text.trim();
if (text.length > 0) {
const textNode = {
type: "text",
content: text
};
const parent = stack[stack.length - 1];
parent.children.push(textNode);
}
}
}
return root;
}
// TEST
const html = `
<div>
<h1>Merhaba</h1>
<p>Parser çalışıyor</p>
</div>
`;
const dom = parseHTML(html);
console.log(JSON.stringify(dom, null, 2));
CSS Nasıl Parse Edilir? (CSSOM Oluşumu) Selector → Rule → Style Tree
HTML parsing sürecinde tarayıcı, sayfanın yapısını oluşturur.
Ancak bu yapı tek başına yeterli değildir; çünkü henüz sayfanın nasıl görüneceği belirlenmemiştir.
İşte bu noktada CSS devreye girer.
CSS, sadece stil tanımlamak için kullanılan bir dil değildir; aynı zamanda tarayıcı tarafından analiz edilip hesaplanan bir kural sistemidir.
Bu kuralların işlenmesi sonucunda oluşan yapı ise CSSOM (CSS Object Model) olarak adlandırılır.
1. CSS Tokenization (Parçalama)HTML’de olduğu gibi, CSS de doğrudan kullanılmaz.
Tarayıcı, gelen CSS kodunu karakter karakter okuyarak anlamlı parçalara ayırır.
Bu parçalar; selector’lar, property’ler ve değerler gibi yapı taşlarını içerir.
Bu aşamada tarayıcı artık düz metin yerine, stil kurallarını temsil eden token’lar ile çalışır.
2. Rule (Kural) OluşumuToken’lar oluşturulduktan sonra, bu parçalar birleştirilerek CSS kuralları oluşturulur.
Her kural iki temel bölümden oluşur: selector ve declaration (özellikler).
Selector, hangi elementlerin etkileneceğini belirler.
Declaration kısmı ise bu elementlere uygulanacak stil kurallarını içerir.
Bu aşamada tarayıcı, artık “hangi elemente ne uygulanacak?” sorusunun cevabını üretir.
3. CSSOM (Style Tree) OluşumuOluşturulan CSS kuralları, bir yapı içerisinde organize edilir.
Bu yapı, CSSOM olarak adlandırılır.
CSSOM, DOM gibi bir ağaç yapısı değildir; daha çok stil kurallarının organize edildiği bir modeldir.
Ancak bu yapı, DOM ile birlikte çalışarak elementlerin nihai görünümünü belirler.
Selector Eşleşmesi (Matching)CSS parsing sürecinin en kritik noktalarından biri, selector eşleşmesidir.
Tarayıcı, her CSS kuralını alır ve DOM içerisindeki elementlerle eşleştirir.
Bu eşleşme sırasında, hangi stilin hangi elemente uygulanacağı belirlenir.
Bu süreç, sayfanın performansını doğrudan etkileyebilir.
Cascade ve Öncelik SistemiBir elemente birden fazla CSS kuralı uygulanabilir.
Bu durumda tarayıcı, hangi kuralın geçerli olacağını belirlemek zorundadır.
Bu karar süreci cascade (katmanlama) olarak adlandırılır.
Selector önceliği, kaynak sırası ve spesifiklik gibi faktörler bu süreci belirler.
Sonuç olarak her element için nihai stil hesaplanır.
Neden Bu Süreç Kritik?CSSOM, sayfanın görünümünü belirleyen ana yapı olduğu için, performans ve render sürecinde kritik rol oynar.
Yanlış yazılmış CSS kuralları, gereksiz hesaplamalara ve performans kaybına neden olabilir.
Bu nedenle CSS parsing sürecini anlamak, sadece stil yazmak değil; tarayıcının nasıl düşündüğünü anlamaktır.
CSS Parser simülasyonu
CSS metni analiz edilerek, stil kurallarına dönüştürülür.
- CSS metni parçalara ayrılır (token)
- Selector ve declaration ayrıştırılır
- Her kural bir obje olarak oluşturulur
- Kurallar CSSOM yapısında saklanır
- DOM ile eşleşmek üzere hazır hale getirilir
function parseCSS(css) {
const rules = [];
let index = 0;
function skipWhitespace() {
while (css[index] === " " || css[index] === "\n") {
index++;
}
}
while (index < css.length) {
skipWhitespace();
let selector = "";
while (css[index] !== "{" && index < css.length) {
selector += css[index];
index++;
}
selector = selector.trim();
const selectors = selector.split(",").map(s => s.trim());
index++; // {
let declarations = [];
while (css[index] !== "}" && index < css.length) {
skipWhitespace();
let property = "";
while (css[index] !== ":" && index < css.length) {
property += css[index];
index++;
}
property = property.trim();
index++; // :
let value = "";
while (css[index] !== ";" && css[index] !== "}" && index < css.length) {
value += css[index];
index++;
}
value = value.trim();
declarations.push({ property, value });
if (css[index] === ";") index++;
}
index++; // }
rules.push({
selectors,
declarations
});
}
return rules;
}
// TEST CSS
const css = `
div {
color: red;
font-size: 16px;
}
p {
color: blue;
}
`;
const cssom = parseCSS(css);
// 🔥 KRİTİK SATIR
console.log(JSON.stringify(cssom, null, 2));
DOM + CSSOM → Render Tree (Görünür Yapı) Structure + Style → Render
HTML parsing sonucunda elde edilen DOM, sayfanın yapısını temsil eder.
CSS parsing sonucunda elde edilen CSSOM ise, bu yapının nasıl görüneceğini belirler.
Ancak bu iki yapı ayrı ayrı kullanılamaz.
Tarayıcı, bu iki sistemi birleştirerek gerçek render edilebilir yapıyı oluşturur.
Render Tree Nedir?Render Tree, DOM ve CSSOM’un birleşmesiyle oluşan, yalnızca görünür elementleri içeren yapıdır.
Bu yapı, tarayıcının ekrana ne çizeceğini belirler.
DOM’daki her element bu yapıya dahil edilmez.
Örneğin display: none olan elementler
render tree’ye dahil edilmez.
Tarayıcı, DOM üzerindeki her node’u inceler.
Daha sonra bu node için geçerli CSS kurallarını bulur.
Bu kurallar birleştirilerek, elementin nihai stili hesaplanır.
Bu işlem sonucunda, stil bilgisi ile birlikte yeni bir node oluşturulur.
Bu node’lar birleşerek render tree’yi oluşturur.
Computed StyleBir elemente uygulanacak stil, tek bir kuraldan gelmez.
Birden fazla CSS kuralı birleşerek nihai stil değerini oluşturur.
Bu sonuca computed style denir.
Render tree, bu computed style bilgisi ile oluşturulur.
Neden Bu Aşama Kritik?Render tree olmadan, tarayıcı neyi çizeceğini bilemez.
Bu yapı, layout ve paint süreçlerinin temelini oluşturur.
Bu nedenle bu aşama, tarayıcı pipeline’ının en kritik noktalarından biridir.
Render Tree simülasyonu
Render tree oluşturulurken, DOM ve CSS kuralları birleştirilir.
- DOM node’ları tek tek incelenir
- Uygun CSS kuralları bulunur
- Computed style hesaplanır
- Görünmeyen node’lar atlanır
- Yeni render node oluşturulur
// Render Tree Simülasyonu
function matchSelector(node, selector) {
return node.tag === selector;
}
function computeStyle(node, cssRules) {
let style = {};
for (let rule of cssRules) {
if (rule.selectors.includes(node.tag)) {
for (let decl of rule.declarations) {
style[decl.property] = decl.value;
}
}
}
return style;
}
function buildRenderTree(domNode, cssRules) {
// text node
if (domNode.type === "text") return null;
const style = computeStyle(domNode, cssRules);
// display none kontrolü
if (style.display === "none") return null;
const renderNode = {
tag: domNode.tag,
style,
children: []
};
for (let child of domNode.children || []) {
const childNode = buildRenderTree(child, cssRules);
if (childNode) {
renderNode.children.push(childNode);
}
}
return renderNode;
}
Layout ve Paint: Hesaplama ve Çizim Süreci Geometry → Pixels
Render tree oluşturulduktan sonra, tarayıcı artık neyi çizeceğini bilir.
Ancak bu yapı hâlâ soyuttur; henüz ekranda görülebilecek bir forma sahip değildir.
Bu nedenle tarayıcı, önce bu yapının geometrisini hesaplar, ardından piksel bazlı çizimi gerçekleştirir.
Bu iki aşama: Layout (hesaplama) ve Paint (çizim) olarak adlandırılır.
Layout (Reflow) Nedir?Layout aşamasında, her elementin boyutu ve konumu hesaplanır.
Tarayıcı, render tree üzerindeki her node’u alır ve bu node’un ekranda nerede duracağını belirler.
Genişlik, yükseklik, margin ve padding gibi değerler bu aşamada hesaplanır.
Bu süreçte tüm sayfa yeniden hesaplanabilir, bu nedenle performans açısından oldukça kritiktir.
Paint (Çizim) Nedir?Layout tamamlandıktan sonra, tarayıcı artık her elementin nerede olduğunu bilir.
Paint aşamasında bu bilgiler kullanılarak ekrana çizim yapılır.
Renkler, arka planlar, metinler ve kenarlıklar bu aşamada piksel olarak oluşturulur.
Bu aşama, kullanıcının gördüğü nihai çıktıyı üretir.
Neden Bu Aşama Kritik?Layout ve paint işlemleri, sayfa performansını doğrudan etkiler.
Gereksiz yeniden hesaplamalar (reflow), sayfanın yavaşlamasına neden olabilir.
Bu nedenle modern tarayıcılar, bu işlemleri optimize etmeye çalışır.
Layout & Paint simülasyonu
Render tree üzerinde her elementin konumu ve boyutu hesaplanır.
- Node konumları hesaplanır
- Boyutlar belirlenir
- Layout bilgisi oluşturulur
- Paint aşamasında piksel çizimi yapılır
// Layout + Paint Simülasyonu
function layout(node, x = 0, y = 0) {
node.layout = {
x,
y,
width: 100,
height: 30,
};
let currentY = y + node.layout.height;
for (let child of node.children || []) {
layout(child, x + 20, currentY);
currentY += child.layout.height;
}
}
function paint(node) {
console.log(`Draw ${node.tag} at (${node.layout.x}, ${node.layout.y})`);
for (let child of node.children || []) {
paint(child);
}
}
// Örnek Render Tree
const renderTree = {
tag: "div",
children: [
{
tag: "h1",
children: [],
},
{
tag: "p",
children: [],
},
],
};
// 🔥 Layout hesapla
layout(renderTree);
// 🔥 Paint (çizim)
paint(renderTree);
Bu Süreç Gerçekte Nasıl Optimize Edilir? Performance Insight
Bu sayfada oluşturduğun simülasyonlar, tarayıcı motorunun temel mantığını anlamanı sağlar.
Ancak gerçek tarayıcılar, bu süreci çok daha karmaşık ve optimize edilmiş şekilde yürütür.
Çünkü modern web sayfaları, yüzlerce hatta binlerce element içerir ve bu elementlerin her biri sürekli değişebilir.
En Kritik Problem: ReflowLayout (reflow) işlemi, tarayıcı için en maliyetli adımlardan biridir.
Bir elementin boyutu veya konumu değiştiğinde, tarayıcı sadece o elementi değil, ona bağlı tüm yapıyı yeniden hesaplamak zorunda kalabilir.
Bu durum, özellikle büyük DOM yapılarında ciddi performans sorunlarına yol açabilir.
Bu nedenle modern tarayıcılar, gereksiz reflow işlemlerini minimize etmeye çalışır.
Repaint ve Rendering MaliyetiPaint (repaint) işlemi, elementlerin yeniden çizilmesini ifade eder.
Renk değişimi gibi basit işlemler bile, belirli bölgelerin tekrar çizilmesini gerektirir.
Her repaint işlemi, GPU ve CPU üzerinde ek yük oluşturur.
Bu nedenle gereksiz stil değişikliklerinden kaçınmak, performans açısından oldukça önemlidir.
Modern Tarayıcı OptimizasyonlarıGünümüzde tarayıcılar, performansı artırmak için birçok optimizasyon uygular.
- Değişiklikleri batch halinde işleme (layout thrashing önleme)
- Sadece etkilenen alanı yeniden hesaplama
- Layer (katman) kullanarak bağımsız render alanları oluşturma
- GPU hızlandırmalı çizim (compositing)
Bu teknikler sayesinde, karmaşık sayfalar bile akıcı şekilde çalışabilir.
Geliştirici Olarak Sen Ne Yapabilirsin?Tarayıcı birçok optimizasyon yapsa da, performansın büyük kısmı geliştiricinin yazdığı koda bağlıdır.
- Gereksiz DOM değişikliklerinden kaçın
- Layout tetikleyen işlemleri minimize et
- Style değişikliklerini toplu şekilde uygula
- Animation’larda transform ve opacity kullan
Bu küçük kararlar, büyük performans farkları yaratabilir.
SonuçArtık bir web sayfasının sadece koddan ibaret olmadığını biliyorsun.
Her satır kod, tarayıcı içerisinde bir süreci tetikler.
Ve bu süreçleri anlamak, seni sadece bir geliştirici değil; sistemi anlayan bir mühendis yapar.
Unutma: İyi yazılmış kod sadece çalışan kod değil, verimli çalışan koddur.