Modern web tarayıcısına yakından bakış (4. bölüm)

Mariko Kosaka

Giriş, birleştiriciye geliyor

Bu, Chrome'un içine baktığımız ve bir web sitesini görüntülemek için kodumuzu nasıl işlediğini incelediğimiz 4 bölümlük blog serisinin sonuncusudur. Önceki yayında, oluşturma sürecine göz atıp derleyici hakkında bilgi edinmiştik. Bu yayında, kullanıcı girişi geldiğinde kompozitörün nasıl sorunsuz bir etkileşim sağladığını inceleyeceğiz.

Tarayıcı açısından giriş etkinlikleri

"Giriş etkinlikleri" ifadesini duyduğunuzda yalnızca metin kutusuna yazmaya veya fareye basmayı düşünebilirsiniz. Ancak tarayıcı açısından "giriş," kullanıcının herhangi bir hareketi anlamına gelir. Fare tekerleği kaydırma bir giriş etkinliğidir ve dokunma veya fareyle üzerine gelme de bir giriş etkinliğidir.

Kullanıcının ekrana dokunması gibi bir hareketi olduğunda, hareketi ilk olarak tarayıcı işlemi alır. Ancak sekmedeki içerikler oluşturma işlemi tarafından işlendiğinden tarayıcı işlemi, yalnızca bu hareketin nerede gerçekleştiğini bilir. Dolayısıyla tarayıcı işlemi, etkinlik türünü (touchstart gibi) ve koordinatlarını oluşturucu işlemine gönderir. Oluşturucu işlemi, etkinlik hedefini bulup bağlı etkinlik dinleyicilerini çalıştırarak etkinliği uygun şekilde işler.

giriş etkinliği
Şekil 1: Tarayıcı işlemi üzerinden oluşturma işlemine yönlendirilen giriş etkinliği

Oluşturucu, giriş etkinlikleri alır

Şekil 2: Görüntü alanı, sayfa katmanlarının üzerinde geziniyor

Önceki yayında, rasterleştirilmiş katmanları birleştirerek kompozitörün kaydırma işlemini nasıl sorunsuz bir şekilde gerçekleştirebileceğine bakmıştık. Sayfaya giriş etkinliği dinleyicisi eklenmemişse Oluşturucu iş parçacığı, ana iş parçacığından tamamen bağımsız yeni bir birleşik çerçeve oluşturabilir. Ancak sayfaya bazı etkinlik dinleyicileri eklenmişse ne olur? Oluşturucu iş parçacığı, etkinliğin işlenmesi gerekip gerekmediğini nasıl anlar?

Hızlı olmayan kaydırılabilir bölgeyi anlama

JavaScript'i çalıştırmak ana iş parçacığının işi olduğundan, bir sayfa birleştirilirken birleştirici iş parçacığı, sayfanın etkinlik işleyicilerinin eklendiği bir bölgeyi "Hızlı Kaydırılabilir Olmayan Bölge" olarak işaretler. Bu bilgilere sahip olan derleyici iş parçacığı, etkinlik söz konusu bölgede gerçekleşirse giriş etkinliğini ana iş parçacığına gönderebilir. Giriş etkinliği bu bölgenin dışından gelirse birleştirici iş parçacığı, ana iş parçacığı beklemeden yeni kareyi birleştirmeye devam eder.

hızlı kaydırılamayan sınırlı bölge
Şekil 3: Hızlı kaydırılabilir olmayan bölgeye yapılan girişin şeması

Etkinlik işleyicileri yazarken dikkat edilmesi gerekenler

Web geliştirmede sık kullanılan bir etkinlik işleme kalıbı, etkinlik yetkilendirmesidir. Etkinlikler balonlaştığından en üstteki öğeye bir etkinlik işleyici ekleyebilir ve görevleri etkinlik hedefine göre devredebilirsiniz. Aşağıdaki gibi kodlar görmüş veya yazmış olabilirsiniz.

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault();
    }
});

Tüm öğeler için yalnızca bir etkinlik işleyici yazmanız gerektiğinden, bu etkinlik yetkilendirme modelinin ergonomisi uygundur. Ancak bu koda tarayıcının bakış açısından bakarsanız sayfanın tamamı artık hızlı kaydırılabilir olmayan bir bölge olarak işaretlenmiştir. Bu nedenle, uygulamanız sayfanın belirli bölümlerinden gelen girişleri önemsemiyor olsa bile, birleştirici iş parçacığının ana iş parçacığıyla iletişim kurması ve her giriş etkinliği geldiğinde bunu beklemesi gerekir. Dolayısıyla, birleştiricinin sorunsuz kaydırma yeteneği geçersiz kılınır.

Sayfanın tamamı, hızlı kaydırılabilir olmayan bölge
Şekil 4: Sayfanın tamamını kapsayan hızlı kaydırılabilir olmayan bölgeye yapılan girişin şeması

Bunun olmasını önlemek için etkinlik işleyicinizde passive: true seçenekleri iletebilirsiniz. Bu, tarayıcıya ana iş parçacığında etkinliği dinlemeye devam etmek istediğinizi ancak derleyicinin yeni kareyi de derleyebileceğini belirtir.

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault()
    }
 }, {passive: true});

Etkinliğin iptal edilebilir olup olmadığını kontrol etme

sayfa kaydırma
Şekil 5: Sayfanın bir kısmının yatay kaydırmaya sabitlendiği bir web sayfası

Bir sayfada, kaydırma yönünü yalnızca yatay kaydırmayla sınırlamak istediğiniz bir kutu olduğunu varsayalım.

İşaretçi etkinliğinizde passive: true seçeneğini kullandığınızda sayfa kaydırma işlemi sorunsuz olabilir, ancak dikey kaydırma, kaydırma yönünü sınırlamak için preventDefault istediğiniz zaman başlatılmış olabilir. event.cancelable yöntemini kullanarak bunu kontrol edebilirsiniz.

document.body.addEventListener('pointermove', event => {
    if (event.cancelable) {
        event.preventDefault(); // block the native scroll
        /*
        *  do what you want the application to do here
        */
    }
}, {passive: true});

Alternatif olarak, etkinlik işleyiciyi tamamen kaldırmak için touch-action gibi bir CSS kuralı da kullanabilirsiniz.

#area {
  touch-action: pan-x;
}

Etkinlik hedefini bulma

isabet testi
Şekil 6: x.y noktasında ne çizildiğini soran boya kayıtlarına bakan ana iş parçacığı

Oluşturucu iş parçacığı ana iş parçacığına bir giriş etkinliği gönderdiğinde ilk çalıştırılan şey, etkinlik hedefini bulmak için bir isabet testidir. İsabet testi, etkinliğin gerçekleştiği nokta koordinatlarının altında ne olduğunu bulmak için oluşturma sürecinde oluşturulan boyama kaydı verilerini kullanır.

Ana iş parçacığına etkinlik dağıtımını en aza indirme

Önceki yayında, tipik ekranımızın ekranı saniyede 60 kez nasıl yenilediğini ve sorunsuz animasyon için ritmi nasıl yakalamamız gerektiğini ele almıştık. Tipik bir dokunmatik ekranlı cihaz, dokunma etkinliğini saniyede 60-120 kez iletirken tipik bir fare ise etkinlikleri saniyede 100 kez iletir. Giriş etkinliği, ekranımızın yenileyebileceğinden daha yüksek doğruluğa sahiptir.

touchmove gibi sürekli bir etkinlik ana iş parçacığına saniyede 120 kez gönderilirse ekranın yenilenme hızına kıyasla aşırı miktarda isabet testi ve JavaScript yürütme işlemi tetiklenebilir.

filtrelenmemiş etkinlikler
Şekil 7: Çerçeve zaman çizelgesini taşarak sayfa engellemesine neden olan etkinlikler

Chrome, ana iş parçacığına yapılan aşırı çağrıları en aza indirmek için sürekli etkinlikleri (wheel, mousewheel, mousemove, pointermove, touchmove gibi) birleştirir ve dağıtımı bir sonraki requestAnimationFrame'den hemen öncesine kadar geciktirir.

birleştirilmiş etkinlikler
Şekil 8: Önceki zaman çizelgesiyle aynı ancak etkinlik birleştirilmiş ve ertelenmiş

keydown, keyup, mouseup, mousedown, touchstart ve touchend gibi ayrı etkinlikler hemen gönderilir.

Kare içi etkinlikleri almak için getCoalescedEvents öğesini kullanın

Çoğu web uygulamasında, birleştirilmiş etkinlikler iyi bir kullanıcı deneyimi sunmak için yeterlidir. Ancak çizim uygulaması gibi şeyler oluşturuyor ve touchmove koordinatlarına göre bir yol yerleştiriyorsanız düzgün bir çizgi çizmek için aralarındaki koordinatları kaybedebilirsiniz. Bu durumda, birleştirilen etkinlikler hakkında bilgi edinmek için işaretçi etkinliğindeki getCoalescedEvents yöntemini kullanabilirsiniz.

getCoalescedEvents
Şekil 9: Sol tarafta düzgün dokunma hareketi yolu, sağ tarafta birleştirilmiş sınırlı yol
window.addEventListener('pointermove', event => {
    const events = event.getCoalescedEvents();
    for (let event of events) {
        const x = event.pageX;
        const y = event.pageY;
        // draw a line using x and y coordinates.
    }
});

Sonraki adımlar

Bu seride, web tarayıcısının işleyiş mekanizmasını ele aldık. DevTools'un neden etkinlik işleyicinize {passive: true} eklemenizi önerdiğini veya komut dosyası etiketinize neden async özelliğini yazabileceğinizi hiç düşünmediyseniz bu serinin, bir tarayıcının daha hızlı ve sorunsuz bir web deneyimi sunmak için bu bilgilere neden ihtiyaç duyduğuna dair biraz açıklık getirdiğini umuyoruz.

Lighthouse'u kullan

Kodunuzun tarayıcıya uygun olmasını istiyorsanız ancak nereden başlayacağınızı bilmiyorsanız Lighthouse'u kullanabilirsiniz. Bu araç, herhangi bir web sitesini denetleyen ve nelerin doğru yapıldığını, nelerin iyileştirilmesi gerektiğini gösteren bir rapor sunar. Denetim listesini okumak, bir tarayıcının ne tür konulara önem verdiği hakkında da fikir edinmenize yardımcı olur.

Performansı nasıl ölçeceğinizi öğrenin

Performans ayarlamaları farklı siteler için değişiklik gösterebilir. Bu nedenle, sitenizin performansını ölçmeniz ve siteniz için en uygun seçeneğe karar vermeniz önemlidir. Chrome Geliştirici Araçları ekibi, sitenizin performansını ölçme ile ilgili birkaç eğitim sunar.

Sitenize Özellik Politikası ekleme

Bir adım daha ileri gitmek istiyorsanız projenizi oluştururken size yol gösterebilecek yeni bir web platformu özelliği olan Özellik Politikası'nı kullanabilirsiniz. Özellik politikasını etkinleştirmek, uygulamanızın belirli davranışını garanti eder ve hata yapmanızı önler. Örneğin, uygulamanızın ayrıştırmayı hiçbir zaman engellemediğinden emin olmak istiyorsanız uygulamanızı senkronize komut dosyaları politikasında çalıştırabilirsiniz. sync-script: 'none' etkinleştirildiğinde, ayrıştırıcıyı engelleyen JavaScript'in yürütülmesi engellenir. Bu, kodunuzun herhangi birinin ayrıştırıcıyı engellemesini önler ve tarayıcı, ayrıştırıcıyı duraklatma konusunda endişelenmemelidir.

Son adım

teşekkür ederim

Web sitesi oluşturmaya başladığımda neredeyse tek endişem kodlarımı nasıl yazacağım ve daha üretken olmama neyin yardımcı olacağıydı. Bunlar önemli olsa da, yazdığımız kodun tarayıcı tarafından nasıl alındığını da düşünmemiz gerekir. Modern tarayıcılar, kullanıcılara daha iyi bir web deneyimi sunmanın yollarına yatırım yapmaya devam etmektedir. Kodumuzu düzenleyerek tarayıcıya yardımcı olmak, kullanıcı deneyiminizi de iyileştirir. Umarım tarayıcılara karşı iyi olma görevinde bana katılırsınız!

Bu serinin ilk taslaklarını inceleyen herkese çok teşekkür ederiz. Bunlardan bazıları şunlardır: Alex Russell, Paul Ireland, Meggin Kearney, Eric Bidelman, Mathias Bynens, Addy Osmani, Kinuko, Charlie1, Yasuko1, Yasuko1.

Bu seriyi beğendiniz mi? 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.