Gereksiz boyamalardan kaçınma

Paul Lewis

Giriş

Bir site veya uygulamanın öğelerini boyamak oldukça maliyetli olabilir ve çalışma zamanı performansımızı olumsuz yönde etkileyebilir. Bu makalede, tarayıcıda boyamayı nelerin tetikleyebileceğine ve gereksiz boyalamaları nasıl önleyebileceğinize kısaca göz atıyoruz.

Resim: Süper hızlı tur

Bir tarayıcının yapması gereken en önemli işlerden biri, DOM ve CSS'nizi ekrandaki piksellere dönüştürmektir. Tarayıcılar bunu oldukça karmaşık bir işlemle yapar. İşe işaretlemeyi okuyarak başlar ve bu sayede bir DOM ağacı oluşturur. CSS ile benzer bir işlem yapar ve CSSOM'u oluşturur. Daha sonra DOM ve CSSOM birleştirilir ve sonuçta, bazı pikselleri boyamaya başlayabileceğimiz bir yapıya ulaşırız.

Boyama sürecinin kendisi ilginç. Chrome'da DOM ve CSS'nin birleşik ağacı, Skia adlı bir yazılım tarafından rasterleştirilir. canvas öğesiyle daha önce oynadıysanız Skia'nın API'si size çok tanıdık gelecektir. Birçok moveTo ve lineTo tarzı işlevin yanı sıra daha gelişmiş işlevler de vardır. Esasen, boyanması gereken tüm öğeler yürütülebilecek bir Skia çağrıları koleksiyonuna ayrıştırılır ve çıktı bir grup bitmap olur. Bu bit eşlemler GPU'ya yüklenir. GPU, parçaları birleştirerek ekrandaki nihai görüntüyü sağlar.

Dom'dan piksele

Buradan çıkarılacak nokta, Skia'nın iş yükünün, öğelerinize uyguladığınız stillerden doğrudan etkilendiğidir. Algoritma açısından ağır stiller kullanıyorsanız Skia'nın daha fazla çalışması gerekir. Colt McAnlis, CSS'nin sayfa oluşturma ağırlığını nasıl etkilediğiyle ilgili bir makale yazmıştır. Daha fazla bilgi için bu makaleyi okumanızı öneririz.

Tüm bunlara rağmen, boyama işleminin yapılması zaman alır ve azaltmazsak yaklaşık 16 ms olan kare bütçemizi aşarız. Kullanıcılar, kare atladığımızı fark eder ve bu durumu takılma olarak algılar. Bu da uygulamamızın kullanıcı deneyimini olumsuz etkiler. Bunu kesinlikle istemeyiz. Bu nedenle, boyama işleminin gerekli olmasına ne tür şeylerin neden olduğunu ve bu konuda neler yapabileceğimizi görelim.

Kaydırma

Tarayıcıda yukarı veya aşağı kaydırdığınızda, içeriğin ekranda görünmeden önce yeniden boyanması gerekir. Her şey yolunda giderse bu küçük bir alan olacaktır. Ancak bu durumda bile çizilmesi gereken öğelere karmaşık stiller uygulanmış olabilir. Bu nedenle, boyayacak küçük bir alanınız olması, sürecin hızlı bir şekilde yapılacağı 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şli simgesine basmanız yeterlidir). Ardından, Geliştirici Araçları açıkken sayfanızla etkileşimde bulunmanız yeterlidir. Yanıp sönen dikdörtgenler, Chrome'un sayfanızın bir bölümünü ne zaman ve nerede boyadığını gösterir.

Chrome Geliştirici Araçları'nda Boyama Dikdörtgenleri'ni Gösterme
Chrome Geliştirici Araçları'nda Boyama Dikdörtgenlerini Gösterme

Kaydırma performansı, sitenizin başarısı için çok önemlidir. Kullanıcılar, sitenizin veya uygulamanızın iyi kaydırmadığını fark eder ve bu durumdan hoşlanmaz. Bu nedenle, kullanıcıların takılma yaşamaması için kaydırma sırasında boyama işleminin hafif tutulması bizim için önemlidir.

Daha önce kaydırma performansıyla ilgili bir makale yazmıştım. Kaydırma performansıyla ilgili ayrıntılar hakkında daha fazla bilgi edinmek istiyorsanız bu makaleyi inceleyebilirsiniz.

Etkileşimler

Etkileşimler de boya işinin başka bir nedenidir: fareyle üzerine gelme, tıklama, dokunma, sürükleme. Kullanıcı bu etkileşimlerden birini (ör. fareyle üzerine gelme) gerçekleştirdiğinde Chrome'un etkilenen öğeyi yeniden boyaması gerekir. Kaydırma işleminde olduğu gibi, büyük ve karmaşık bir boyama işlemi gerekiyorsa kare hızının düştüğünü görürsünüz.

Herkes güzel ve akıcı etkileşim animasyonları ister. Bu nedenle, animasyonumuzda değişen stillerin bize çok fazla zaman kaybettirip kaybettirmediğini tekrar kontrol etmemiz gerekir.

Talihsiz bir kombinasyon

Pahalı boyalarla yapılan bir demo
Pahalı boyalarla yapılan bir demo

Ekranı kaydırırken aynı anda fareyi hareket ettirirsem ne olur? Ekranı kaydırırken bir öğeyle yanlışlıkla "etkileşimde bulunabilirim" ve pahalı bir boyayı tetikleyebilirim. Bu da yaklaşık 16,7 ms olan kare bütçemi (saniyede 60 kareye ulaşmak için bu sürenin altında kalmamız gerekir) aşmama neden olabilir. Tam olarak neyi kastettiğimi göstermek için bir demo oluşturdum. Kaydırırken ve farenizi hareket ettirirken fareyle üzerine gelme efektlerinin etkinleştiğini görebilirsiniz. Ancak Chrome'un Geliştirici Araçları'nın bu konuda ne düşündüğünü görelim:

Chrome'un Geliştirici Araçları pahalı kareleri gösteriyor
Chrome'un pahalı kareleri gösteren Geliştirici Araçları

Yukarıdaki resimde, fareyle bloklardan birinin üzerine geldiğimde DevTools'un boyama işlemini kaydettiğini görebilirsiniz. Demomda anlattığım son derece yoğun stillerden yararlandım ve ara sıra kare bütçemi aşmaya çalışıyorum. Bu boyama işini gereksiz yere yapmak istemem. Özellikle de yapılacak başka işler varken ekranı kaydırırken bunu yapmak istemem.

Peki bunun olmasını nasıl önleyebiliriz? Bu sorunun çözümü oldukça basittir. Buradaki püf noktası, fareyle üzerine gelme efektlerini devre dışı bırakacak ve bunları tekrar etkinleştirmek için bir zamanlayıcı ayarlayacak bir scroll işleyici eklemektir. Yani siz ekranı kaydırırken pahalı etkileşim boyamaları gerçekleştirmemiz gerekmeyeceğini garanti ediyoruz. Yeterince uzun süre durduğunuzda bunları 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ördüğünüz gibi, fareyle üzerine gelme efektlerine "izin verilip verilmediğini" izlemek için body bölümünde bir sınıf kullanıyoruz ve temel stiller bu sınıfın mevcut olmasını gerektiriyor:

/* 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 yararlanan kullanıcılar için kritik öneme sahiptir ve boyama iş yükünüzü her zaman 16 ms'nin altında tutmayı hedeflemelisiniz. Bu konuda size yardımcı olması için, ortaya çıkan performans sorunlarını belirleyip düzeltmek amacıyla geliştirme süreciniz boyunca Geliştirici Araçları'nı kullanarak entegrasyon yapmanız gerekir.

Özellikle boya ağırlıklı öğelerde yanlışlıkla yapılan etkileşimler çok maliyetli olabilir ve oluşturma performansını düşürür. Gördüğünüz gibi, bu sorunu düzeltmek için küçük bir kod parçası kullanabiliriz.

Sitelerinize ve uygulamalarınıza göz atın. Biraz boya koruması gerekiyor mu?