Gereksiz boyamalardan kaçınma

Paul Lewis

Giriş

Bir site veya uygulamaya ait unsurları boyamak çok pahalıya mal olabilir ve çalışma zamanı performansımızı olumsuz yönde etkileyebilir. Bu makalede, tarayıcıda boyamayı nelerin tetikleyebileceğine ve gereksiz boyamaların gerçekleşmesini nasıl önleyebileceğinize hızlı bir şekilde göz atacağız.

Boyama: Çok hızlı bir tur

Bir tarayıcının gerçekleştirmesi gereken ana görevlerden biri, DOM ve CSS'nizi ekranda piksellere dönüştürmektir ve bunu oldukça karmaşık bir işlemden geçirir. İlk olarak işaretlemeyi okur ve buradan bir DOM ağacı oluşturur. CSS ile benzer bir şey yapar ve buradan CSSOM'yi oluşturur. Daha sonra DOM ve CSSOM birleştirilir ve nihayetinde, bazı pikselleri boyamaya başlayabileceğimiz bir yapıya ulaşırız.

Boyama işleminin kendisi ilgi çekicidir. Chrome'da, DOM ve CSS'yi birleştiren ağaç, Skia adı verilen bir yazılım tarafından pikselleştirilir. Skia'nın canvas öğesini daha önce oynamış olsaydınız, size çok tanıdık gelecek; moveTo ve lineTo tarzı birçok işlevin yanı sıra daha gelişmiş bir dizi işlev de vardır. Esas olarak, boyanması gereken tüm öğeler, çalıştırılabilecek Skia çağrıları koleksiyonuna ayrıştırılır ve çıktı olarak bir dizi bit eşlem elde edilir. Bu bit eşlemler GPU'ya yüklenir ve GPU, bu bit eşlemleri birleştirerek ekrandaki son resmi elde etmemize yardımcı olur.

Dom'dan piksele

Buradan çıkarılması gereken tek şey, Skia'nın iş yükünün, öğelerinize uyguladığınız stillerden doğrudan etkilenmesidir. Algoritmaya dayalı olarak ağır stiller kullanırsanız Skia'nın yapması gereken daha fazla şey olur. Colt McAnlis, CSS'nin sayfa oluşturma ağırlığını nasıl etkilediğiyle ilgili bir makale yazdı. Bu nedenle, daha fazla bilgi edinmek için bu makaleyi okumalısınız.

Tüm bunların yanında, boya işlerinin tamamlanması zaman alır ve bu işi azaltmazsak yaklaşık 16 ms'lik kare bütçemizi aşacağız. Kullanıcılar kareleri kaçırdığımızı fark eder ve bunu olumsuz olarak görür ve bu da uygulamamızın kullanıcı deneyimini olumsuz etkiler. Bunu gerçekten istemeyiz. Öyleyse şimdi ne tür şeylerin boyamanın gerekli olmasına neden olduğuna ve bu konuda neler yapabileceğimize bakalım.

Kaydırma

Tarayıcıda sayfayı yukarı veya aşağı kaydırdığınızda, içeriğin ekranda görünebilmesi için önce yeniden boyanması gerekir. Her şeyin yolunda olması yalnızca küçük bir alan olacaktır, ancak bu durumda bile çizilmesi gereken öğelere karmaşık stiller uygulanabilir. Küçük bir boya alanınız olması her şeyin hızlıca gerçekleşeceği anlamına gelmez.

Hangi alanların yeniden boyandığını görmek için Chrome'un Geliştirici Araçları'ndaki "Boya Dikdörtgenlerini Göster" özelliğini kullanabilirsiniz (sağ alt köşedeki küçük dişliye basmanız yeterlidir). Ardından, Geliştirici Araçları açıkken sayfanızla etkileşimde bulunduğunuzda, Chrome'un sayfanızın bir bölümünü ne zaman ve nerede boyadığını gösteren yanıp sönen dikdörtgenler görürsünüz.

Chrome Geliştirici Araçları'nda Boya Dikdörtgenlerini Göster
Chrome Geliştirici Araçları'nda Boya Dikdörtgenlerini göster

Kaydırma performansı, sitenizin başarısı için kritik öneme sahiptir. Kullanıcılar sitenizde veya uygulamanızda kaydırmanın iyi sonuç vermediğini gerçekten fark eder ve bunu beğenmez. Bu nedenle, kullanıcıların olumsuzluk görmemesi için parlama sırasında boya işlerinin ışığını korumak bizim için yararlı olacaktır.

Daha önce kaydırma performansıyla ilgili bir makale yazmıştım. Kaydırma performansı hakkında daha fazla bilgi edinmek istiyorsanız bu makaleye bakabilirsiniz.

Etkileşimler

Boya işlemlerinin bir başka nedeni de etkileşimlerdir: fareyle üzerine gelme, tıklama, dokunma, sürükleme. Kullanıcı bu etkileşimlerden birini gerçekleştirdiğinde (ör. fareyle üzerine gelindiğinde), Chrome'un etkilenen öğeyi yeniden boyaması gerekir. Ayrıca, kaydırma işleminde olduğu gibi, büyük ve karmaşık bir boyama işlemi varsa kare hızında düşüş görürsünüz.

Herkes hoş, akıcı etkileşim animasyonları ister. Bu yüzden, animasyonumuzda değişen stillerin bize çok fazla zaman kazandırıp harcamadığını da görmemiz gerekir.

Ne yazık ki bir kombinasyon

Pahalı boyaların yer aldığı bir tanıtım
Pahalı boyaların gösterildiği bir tanıtım

Sayfayı kaydırdığımda fareyi aynı anda hareket ettirirsem ne olur? Bir öğeyi kaydırarak yanlışlıkla "etkileşime girmem" mümkün ve pahalı bir boyayı tetikleyebiliyor. Bu da beni yaklaşık 16,7 ms'lik kare bütçeme (saniyede 60 kareye ulaşmak için bunun altında kalmamız gereken süre) itebilir. Tam olarak ne demek istediğimi göstermek için bir demo oluşturdum. Ekranı kaydırıp fareyi hareket ettirdikçe fareyle üzerine gelme efektlerinin etkinleşeceğini umuyoruz. Chrome Geliştirici Araçları'nın bunu nasıl yaptığını görelim:

Chrome'un Geliştirici Araçları pahalı çerçeveler gösteriyor
Chrome'un Geliştirici Araçları pahalı çerçeveler gösteriyor

Yukarıdaki resimde, bloklardan birinin üzerine geldiğimde Geliştirici Araçları'nın boya işini kaydettiğini görebilirsiniz. Anlatmak için demomda çok ağır stiller kullandım ve zaman zaman kare bütçemi artırıyorum. İstediğim son şey, bu boya işini gereksiz bir şekilde yapmak zorunda kalmak. Bunu özellikle de yapılacak başka işler varken kaydırma sırasında yapmak istiyorum!

Peki bunun olmasını nasıl engelleyebiliriz? Bu gerçekleştiği için çözümü uygulamak oldukça basittir. Buradaki püf noktası, fareyle üzerine gelme efektlerini devre dışı bırakacak bir scroll işleyici eklemek ve bunları tekrar etkinleştirmek için bir zamanlayıcı ayarlamaktır. Yani, sayfayı kaydırırken pahalı etkileşim boyaları yapmak zorunda kalmayacağımızı garanti ediyoruz. Yeterince uzun bir süre boyunca durdurduktan sonra tekrar açmanın güvenli olduğunu düşünürüz.

Kod:

// Used to track the enabling of hover effects
var enableTimer = 0;

/*
 * Listen for a scroll and use that to remove
 * the possibility of hover effects
 */
window.addEventListener('scroll', function() {
  clearTimeout(enableTimer);
  removeHoverClass();

  // enable after 1 second, choose your own value here!
  enableTimer = setTimeout(addHoverClass, 1000);
}, false);

/**
 * Removes the hover class from the body. Hover styles
 * are reliant on this class being present
 */
function removeHoverClass() {
  document.body.classList.remove('hover');
}

/**
 * Adds the hover class to the body. Hover styles
 * are reliant on this class being present
 */
function addHoverClass() {
  document.body.classList.add('hover');
}

Görebileceğiniz gibi, fareyle üzerine gelme efektlerinin "izin verildi" olup olmadığını izlemek için gövdede bir sınıf kullanıyoruz ve temel stiller, bu sınıfın mevcut olmasını temel alıyor:

/* Expect the hover class to be on the body
 before doing any hover effects */
.hover .block:hover {
 …
}

Hepsi bu kadar!

Sonuç

Oluşturma performansı, uygulamanızdan keyif alan kullanıcılar için kritik öneme sahiptir. Bu nedenle boya iş yükünüzü her zaman 16 ms'nin altında tutmayı hedeflemelisiniz. Bu konuda size yardımcı olmak için geliştirme süreciniz boyunca Geliştirici Araçları'nı kullanarak entegrasyon sağlamalısınız. Böylece, ortaya çıkan performans sorunlarını belirleyip düzeltebilirsiniz.

Özellikle boya ağırlıklı öğelerde meydana gelen istenmeyen etkileşimler çok maliyetli olabilir ve oluşturma performansını düşürebilir. Gördüğünüz gibi bunu düzeltmek için küçük bir kod parçası kullanabiliyoruz.

Sitelerinize ve uygulamalarınıza göz atın. Boya korumasıyla neler yapabilirler?