Oluşturucu işleminin işleyiş şekli
Bu, tarayıcıların işleyişine odaklanan 4 bölümlük blog serisinin 3. bölümüdür. Daha önce çoklu işlem mimarisini ve gezinme akışını ele almıştık. Bu yayında, oluşturma işleminin içinde neler olduğuna bakacağız.
Oluşturucu işlemi, web performansının birçok yönünü etkiler. Oluşturucu sürecinde çok fazla işlem gerçekleştiği için bu yayında yalnızca genel bir bakış sunulmaktadır. Daha ayrıntılı bilgi edinmek isterseniz Web Temel Bilgileri'nin Performans bölümünde daha birçok kaynak bulabilirsiniz.
Oluşturucu işlemleri web içeriklerini işler
Oluşturucu işlemi, sekme içinde gerçekleşen her şeyden sorumludur. Bir oluşturma işleminde ana iş parçacığı, kullanıcıya gönderdiğiniz kodun çoğunu işler. Web çalışanı veya hizmet çalışanı kullanıyorsanız JavaScript'inizin bazı bölümleri bazen çalışan iş parçacıkları tarafından işlenir. Bir sayfayı verimli ve sorunsuz bir şekilde oluşturmak için bir oluşturucu ve raster iş parçacığı da oluşturucu işlemlerinde çalıştırılır.
Oluşturucu işleminin temel görevi, HTML, CSS ve JavaScript'i kullanıcının etkileşimde bulunabileceği bir web sayfasına dönüştürmektir.

Ayrıştırma
DOM oluşturma
Oluşturucu işlem bir gezinme için bir taahhüt mesajı aldığında ve HTML verileri almaya başladığında ana mesaj dizisi, metin dizesini (HTML) ayrıştırmaya ve DocumentObject Model'e (DOM) dönüştürmeye başlar.
DOM, bir tarayıcının sayfanın dahili temsilidir. Ayrıca, web geliştiricinin JavaScript aracılığıyla etkileşim kurabileceği veri yapısı ve API'dir.
Bir HTML belgesinin DOM'a ayrıştırılması HTML Standardı tarafından tanımlanır. Bir tarayıcıya HTML beslemenin hiçbir zaman hata oluşturmadığını fark etmiş olabilirsiniz. Örneğin, eksik kapanış </p>
etiketi geçerli bir HTML'dir. Hi! <b>I'm <i>Chrome</b>!</i>
gibi hatalı işaretlemeler (b etiketi i etiketinden önce kapatılır) Hi! <b>I'm <i>Chrome</i></b><i>!</i>
yazmışsınız gibi değerlendirilir. Bunun nedeni, HTML spesifikasyonunun bu hataları sorunsuz bir şekilde ele alacak şekilde tasarlanmış olmasıdır. Bu işlemlerin nasıl yapıldığını merak ediyorsanız HTML spesifikasyonunun "Ayrıştırıcıda hata işleme ve garip durumlara giriş" bölümünü okuyabilirsiniz.
Alt öğe yükleme
Web siteleri genellikle resim, CSS ve JavaScript gibi harici kaynaklar kullanır. Bu dosyaların ağdan veya önbellekten yüklenmesi gerekir. Ana iş parçacığı, DOM oluşturmak için ayrıştırma işlemi sırasında bulduğu öğeleri tek tek isteyebilir ancak hızlandırmak amacıyla "önyükleme tarayıcı" eşzamanlı olarak çalıştırılır.
HTML dokümanında <img>
veya <link>
gibi öğeler varsa ön yükleme tarayıcı, HTML ayrıştırıcı tarafından oluşturulan jetonlara göz atar ve tarayıcı işlemindeki ağ iş parçacığına istek gönderir.

JavaScript, ayrıştırmayı engelleyebilir
HTML ayrıştırıcı bir <script>
etiketi bulduğunda HTML belgesinin ayrıştırmasını duraklatır ve JavaScript kodunu yüklemesi, ayrıştırması ve yürütmesi gerekir. Neden? Çünkü JavaScript, DOM yapısının tamamını değiştiren document.write()
gibi öğeleri kullanarak belgenin şeklini değiştirebilir (HTML spesifikasyonundaki ayrıştırma modeline genel bakış bölümünde güzel bir şema vardır). Bu nedenle, HTML ayrıştırıcının HTML dokümanının ayrıştırılmasını devam ettirebilmek için JavaScript'in çalışmasını beklemesi gerekir. JavaScript yürütme sırasında neler olduğunu merak ediyorsanız V8 ekibinin bu konuyla ilgili konuşmaları ve blog yayınları mevcuttur.
Tarayıcıya kaynakları nasıl yüklemek istediğinizi belirtme
Web geliştiricileri, kaynakları düzgün bir şekilde yüklemek için tarayıcıya ipucu göndermenin birçok yolunu kullanabilir.
JavaScript'inizde document.write()
kullanılmıyorsa <script>
etiketine async
veya defer
özelliğini ekleyebilirsiniz. Ardından tarayıcı, JavaScript kodunu eşzamansız olarak yükleyip çalıştırır ve ayrıştırmayı engellemez. Uygun olduğunda JavaScript modülü de kullanabilirsiniz. <link rel="preload">
, tarayıcıya kaynağın mevcut gezinme için kesinlikle gerekli olduğunu ve en kısa sürede indirmek istediğinizi bildirmenin bir yoludur. Bu konuda daha fazla bilgiyi Kaynak Önceliklendirmesi – Tarayıcının Size Yardım Etmesini Sağlama başlıklı makalede bulabilirsiniz.
Stil hesaplama
Sayfa öğelerine CSS'de stil uygulayabileceğimiz için sayfanın nasıl görüneceğini bilmek için DOM'a sahip olmak yeterli değildir. Ana iş parçacığı CSS'yi ayrıştırır ve her DOM düğümü için hesaplanan stili belirler. Bu, CSS seçicilere göre her öğeye ne tür bir stilin uygulandığıyla ilgili bilgilerdir. Bu bilgileri DevTools'un computed
bölümünde görebilirsiniz.

Her DOM düğümünün, CSS sağlamasanız bile hesaplanmış bir stili vardır. <h1>
etiketi, <h2>
etiketinden daha büyük gösterilir ve her öğe için kenar boşlukları tanımlanır. Bunun nedeni, tarayıcının varsayılan bir stil sayfasına sahip olmasıdır. Chrome'un varsayılan CSS'sinin nasıl olduğunu öğrenmek istiyorsanız kaynak kodunu buradan görebilirsiniz.
Düzen
Oluşturucu işlemi artık dokümanın yapısını ve her bir düğümün stillerini biliyordur ancak bu, bir sayfayı oluşturmak için yeterli değildir. Arkadaşınıza telefonda bir tabloyu anlatmaya çalıştığınızı düşünün. "Büyük kırmızı bir daire ve küçük mavi bir kare var", arkadaşınızın resmin tam olarak nasıl görüneceğini anlaması için yeterli bilgi değildir.

Düzenleme, öğelerin geometrisini bulma işlemidir. Ana iş parçacığı, DOM ve hesaplanmış stilleri tarar ve x y koordinatları ve sınırlayıcı kutu boyutları gibi bilgiler içeren düzen ağacını oluşturur. Sayfa düzeni ağacı, DOM ağacına benzer bir yapıya sahip olabilir ancak yalnızca sayfada görünenlerle ilgili bilgileri içerir. display: none
uygulanırsa bu öğe düzen ağacının bir parçası değildir (ancak visibility: hidden
içeren bir öğe düzen ağacındadır). Benzer şekilde, p::before{content:"Hi!"}
gibi bir içeriğe sahip bir sözde öğe uygulanırsa DOM'de olmasa bile düzen ağacına dahil edilir.

Bir sayfanın düzenini belirlemek zor bir iştir. Üstten alta doğru blok akış gibi en basit sayfa düzenlerinde bile yazı tipinin boyutu ve satır aralarının nerede olacağı dikkate alınmalıdır. Bunlar, paragrafın boyutunu ve şeklini etkiler. Bu da sonraki paragrafın nerede olması gerektiğini etkiler.
CSS, öğenin bir tarafa kaymasını sağlayabilir, taşma öğesini maskeleyebilir ve yazı yönlerini değiştirebilir. Bu düzen aşamasının ne kadar önemli olduğunu tahmin edebilirsiniz. Chrome'da, düzen üzerinde bir mühendis ekibi çalışır. Çalışmalarının ayrıntılarını görmek istiyorsanız BlinkOn Konferansı'ndaki birkaç konuşmayı izleyebilirsiniz.
Boyama yapın

DOM, stil ve düzene sahip olmak, bir sayfayı oluşturmak için yeterli değildir. Bir resmi yeniden üretmeye çalıştığınızı varsayalım. Öğelerin boyutunu, şeklini ve konumunu bilseniz de bunları hangi sırayla boyayacağınıza karar vermeniz gerekir.
Örneğin, z-index
belirli öğeler için ayarlanabilir. Bu durumda, HTML'de yazılan öğelerin sırasına göre boyama işlemi yanlış oluşturmaya neden olur.

Bu boyama adımında ana iş parçacığı, boyama kayıtları oluşturmak için düzen ağacında gezinir. Boyama kaydı, "önce arka plan, sonra metin, sonra dikdörtgen" gibi boyama işlemiyle ilgili bir nottur. JavaScript kullanarak <canvas>
öğesinde çizim yaptıysanız bu işlem size tanıdık gelebilir.

Oluşturma ardışık düzenini güncellemek maliyetlidir
Oluşturma ardışık düzeninde anlaşılması gereken en önemli nokta, her adımda yeni veriler oluşturmak için önceki işlemin sonucunun kullanılmasıdır. Örneğin, düzen ağacında bir değişiklik olursa dokümanın etkilenen bölümleri için boyama sırasının yeniden oluşturulması gerekir.
Öğeleri animasyonlu hale getiriyorsanız tarayıcının bu işlemleri her kare arasında çalıştırması gerekir. Ekranlarımızın çoğu ekranı saniyede 60 kez (60 fps) yeniler. Ekrandaki öğeleri her karede hareket ettirdiğinizde animasyon insan gözüne düzgün görünür. Ancak animasyon, aralarındaki kareleri atlarsa sayfa "takılmalı" görünür.

Oluşturma işlemleriniz ekran yenilemesini takip ediyor olsa bile bu hesaplamalar ana iş parçacığında çalışır. Bu da uygulamanız JavaScript'i çalıştırırken engellenebileceği anlamına gelir.

JavaScript işlemini küçük parçalara bölebilir ve requestAnimationFrame()
kullanarak her karede çalışacak şekilde planlayabilirsiniz. Bu konu hakkında daha fazla bilgi için lütfen JavaScript'i yürütmeyi optimize etme başlıklı makaleyi inceleyin. Ana iş parçacığının engellenmesini önlemek için JavaScript'inizi Web İşleyiciler'de de çalıştırabilirsiniz.

Birleştirme
Bir sayfayı nasıl çizersiniz?
Tarayıcı, dokümanın yapısını, her öğenin stilini, sayfanın geometrisini ve boyama sırasını bildiğine göre sayfayı nasıl çizer? Bu bilgilerin ekranda piksele dönüştürülmesine rasterleştirme denir.
Bunu yapmanın basit bir yolu, görüntü alanının içindeki parçaları rasterleştirmek olabilir. Kullanıcı sayfayı kaydırırsa rasterlenmiş çerçeveyi hareket ettirin ve daha fazla rasterleyerek eksik parçaları doldurun. Chrome, ilk yayınlandığında rasterleştirmeyi bu şekilde gerçekleştiriyordu. Ancak modern tarayıcı, birleştirme adı verilen daha karmaşık bir işlem yürütür.
Kompozit oluşturma nedir?
Birleştirme, bir sayfanın bölümlerini katmanlara ayıran, bunları ayrı ayrı rasterleştiren ve birleştirici iş parçacığı adı verilen ayrı bir iş parçacığında sayfa olarak birleştiren bir tekniktir. Kaydırma gerçekleşirse katmanlar zaten rasterleştirildiğinden tek yapması gereken yeni bir kare oluşturmaktır. Animasyon, katmanları hareket ettirerek ve yeni bir kare oluşturarak da aynı şekilde yapılabilir.
Katmanlar panelini kullanarak web sitenizin DevTools'ta katmanlara nasıl bölündüğünü görebilirsiniz.
Katmanlara bölme
Ana iş parçacığı, hangi öğelerin hangi katmanlarda olması gerektiğini bulmak için katman ağacını oluşturmak üzere düzen ağacında gezinir (bu bölüm, DevTools performans panelinde "Katman Ağacını Güncelle" olarak adlandırılır). Bir sayfanın ayrı katman olması gereken belirli bölümleri (kaydırmalı yan menü gibi) ayrı katman olarak oluşturulmuyorsa CSS'de will-change
özelliğini kullanarak tarayıcıya ipucu verebilirsiniz.

Her öğeye katman eklemek isteyebilirsiniz ancak çok sayıda katmanda oluşturma işlemi yapmak, sayfanın küçük bölümlerini her karede rasterleştirmekten daha yavaş işleme neden olabilir. Bu nedenle, uygulamanızın oluşturma performansını ölçmeniz çok önemlidir. Konu hakkında daha fazla bilgi için Yalnızca Oluşturucu Özelliklerini Kullanma ve Katman Sayısını Yönetme başlıklı makaleyi inceleyin.
Ana iş parçacığının dışında raster ve birleştirme
Katman ağacı oluşturulduktan ve boyama siparişleri belirlendikten sonra ana iş parçacığı bu bilgileri birleştirici iş parçacığına bağlar. Daha sonra, karıştırıcı iş parçacığı her katmanı rasterleştirir. Katmanlar, bir sayfanın tamamı kadar büyük olabileceğinden, birleştirici iş parçacığı bunları karolara böler ve her karoyu raster iş parçacılarına gönderir. Rastırsal iş parçacıları her karoyu rasterleştirir ve GPU belleğinde depolar.

Oluşturucu iş parçacığı, görüntü alanındaki (veya yakınındaki) öğelerin önce rasterleştirilmesi için farklı raster iş parçacıklarına öncelik verebilir. Katmanlar, yakınlaştırma gibi işlemleri gerçekleştirmek için farklı çözünürlüklerde birden fazla döşeme de içerir.
Kartlar rasterleştirildikten sonra, bir resimlendirici çerçevesi oluşturmak için resimlendirici iş parçacığı çizim dörtgenleri adlı kart bilgilerini toplar.
Dörtgen çizme | Kartın bellekteki konumu ve sayfa kompozisyonu dikkate alınarak kartın sayfanın neresinde çizileceği gibi bilgileri içerir. |
Birleştirici çerçevesi | Bir sayfanın çerçevesini temsil eden dörtgen çizim koleksiyonu. |
Ardından, bir kompozitör çerçevesi IPC aracılığıyla tarayıcı sürecine gönderilir. Bu noktada, tarayıcı kullanıcı arayüzü değişikliği için kullanıcı arayüzü iş parçacığından veya uzantılar için diğer oluşturma işlemlerinden başka bir derleyici çerçevesi eklenebilir. Bu birleştirici kareler, ekranda gösterilmek üzere GPU'ya gönderilir. Bir kaydırma etkinliği gelirse kompozitör iş parçacığı, GPU'ya gönderilecek başka bir kompozitör çerçevesi oluşturur.

Birleştirmenin avantajı, ana iş parçacığı kullanılmadan yapılmasıdır. Oluşturucu iş parçacığının stil hesaplamasını veya JavaScript'in yürütülmesini beklemesi gerekmez. Bu nedenle, yalnızca animasyonların birleştirilmesi, sorunsuz performans için en iyi seçenek olarak kabul edilir. Düzenleme veya boyamanın tekrar hesaplanması gerekiyorsa ana iş parçacığının dahil edilmesi gerekir.
Özet
Bu yayında, ayrıştırmadan birleştirmeye kadar olan oluşturma ardışık düzenine baktık. Artık bir web sitesinin performans optimizasyonu hakkında daha fazla bilgi edinebilirsiniz.
Bu serinin bir sonraki ve son yayınında, derleyici iş parçasını daha ayrıntılı bir şekilde inceleyip mouse move
ve click
gibi kullanıcı girişleri geldiğinde ne olduğunu göreceğiz.
Yayından memnun kaldınız mı? Gelecekteki bir yayınımız için sorularınız veya önerileriniz varsa aşağıdaki yorum bölümünden veya Twitter'daki @kosamari hesabından bizimle iletişime geçebilirsiniz.