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. Ardından DOM ve CSSOM birleştirilir ve sonunda bazı pikselleri boyamaya başlayabileceğimiz bir yapıya ulaşırız.
Resim yapma süreci ilgi çekicidir. 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 bitmap'ler GPU'ya yüklenir ve GPU, ekranda nihai resmi göstermek için bunları birleştirerek yardımcı olur.

Buradan çıkarılacak sonuç, 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. Boyamanız gereken alanın küçük olması, işlemin hızlı olacağı 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, DevTools açıkken sayfanızla etkileşime geçin. Chrome'un sayfanızı nereye ve ne zaman boyadığını gösteren yanıp sönen dikdörtgenler görürsünüz.

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
Fareyle üzerine gelme, tıklama, dokunma ve sürükleme gibi etkileşimler de boya çalışmasının bir başka nedenidir. 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 gerekiyor.
Talihsiz bir kombinasyon

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 ne demek istediğimi göstermek için bir demo oluşturdum. Farenizi kaydırırken ve 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:

Yukarıdaki resimde, fareyle bloklardan birinin üzerine geldiğimde DevTools'un boyama işlemini kaydettiğini görebilirsiniz. Bu noktayı vurgulamak için demomda çok ağır stiller kullandım. Bu nedenle, çerçeve bütçemi aşıyorum ve bazen aşı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 bunu 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 şu şekildedir:
// 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ı, kullanıcıların uygulamanızdan keyif alabilmesi için çok önemlidir. Bu nedenle, boyama iş yükünüzü her zaman 16 ms'nin altında tutmaya çalışmalısınız. Bunu yapmanıza yardımcı olması için, geliştirme süreciniz boyunca DevTools'u kullanarak entegrasyon yapın. Böylece, darboğazları ortaya çıktıklarında tespit edip düzeltebilirsiniz.
Ö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?