Takip ettiğim ve büyük zevkle okuduğum bloglardan biri Steve Souders'in High Performance Web Sites isimli blogu. İtiraf etmeliyim ki ilk okuduğumda pek aklıma yatmamıştı; yüklenecek resimleri birleştirmek, tarayıcıların kendilerine özgü yükleme davranışları... Bana erken iyileştirme gibi gelmişti. Fakat okumaya devam ettiğimde bu endişelerin yanlış olduğunu anladım. Steve Souders yüksek performanslı web siteleri konusunda bir uzman ve anlattıkları da çoğunlukla testlerle desteklenmiş, gerçekçi teknikler. Eğer takip etmiyorsanız, web uygulamaları geliştirmeseniz bile, RSS okuyucunuza eklemenizi öneririm.
İyileştirme Teknikleri
İyileştirme tekniklerini iki grupta toplayabiliriz:
- Yüklenecek verinin boyutunu azaltmaya yönelik teknikler.
- Minifying: CSS ve JavaScript dosyalarında yorumları ve gerekmeyen boşlukları yok ederek dosya boyutunu azaltmaya dayanıyor. Hatta YUI Compressor ve Closure daha da ileri giderek JavaScript kodunda, işleyişi aynı kalmak kaydıyla, düzenlemeler yapabiliyor.
- Gzip Sıkıştırma: Web tarayıcıları uzun zamandır gzip ile sıkıştırılmış içeriği kabul edebiliyor. Biraz önce, deneme amacıyla 13 KB'lık bir metin dosyasını sıkıştırdım, sonuç 4 KB oldu. Üçte ikilik sıkıştırma oranı hiç de fena değil.
- HTTP isteklerini azaltmaya yönelik teknikler.
- Birleştirme: CSS ve JavaScript dosyaları, sıraları bozulmamak şartıyla, arka arkaya eklenerek tek bir dosya, dolayısıyla tek bir HTTP isteği haline getirilebilir. Birleştirilmiş dosyalarda gzip sıkıştırma da daha iyi sonuç verebilir. Benzer şekilde arkaplan resimleri de bir dosyada toplanıp, oluşturulan sprite üzerindeki koordinatları kullanarak istenen resim tekrar elde edilebilir.
- Data URI'ler: Kullanılan resimleri (veya başka tür dosyaları), CSS (veya JavaScript veya HTML) içine gömmek için data: URI'ler kullanılabilir. Böylece gömülü dosyalar için HTTP isteği yapılması gerekmez.
Tüm bu iyileştirmeleri yapmak güzel ama, JavaScript dosyalarımı birleştirip üzerine bir de minify ettikten sonra bir değişiklik yapmak istediğimde ne olacak diye düşünüyor olabilirsiniz. Yukarıda saydığım teknikleri körü körüne uygulamak yerine mantıklı bir yol izlemekte fayda var:
- Her şeyden önce otomatikleştirilebilecek her şeyi otomatikleştirmek ilkesi geliyor. Yukarıdaki örnekten hareketle betik dosyaları ayrı ayrı, sıkıştırılmamış olarak düzenlenip uygulama yayınlanacağı zaman birleştirme ve sıkıştırma uygulanabilir. Hatta daha da ileri gidilerek yazılımın değişen dosyaları fark ederek gerekli işlemleri kendi kendine uygulaması sağlanabilir. (django_compressor böyle yapıyor)
- Arkaplan resmi birleştirmede endişe ettiğim konu tasarımın düzenlenmesi aşamasında işlerin karışma olasılığıydı. Fakat sprite'ların hangi resimlerden oluşturulacağının dikkatlice seçilmesi durumunda, aksine düzenleme yapmanın daha da kolaylaşabileceğini gördüm. İşe aynı tasarım elemanına ait resimleri birleştirmeyle başlayın. Karmaşık yerleştirme düzenlerinden kaçının, mümkün olduğu kadar sadece yan yana veya alt alta yerleştirin. Resim aralarına ve sprite çevresine transparan boşluk koymayı ihmal etmeyin. Mümkün olduğu kadar aynı sayfada yüklenecek resimleri birleştirin, yarısı kullanılacak diye tüm bir sprite yüklenmesin. Tüm resimler sprite olsun diye zorlamayın, zaten bu saydığım noktalara dikkat ederseniz olmayacaktır.
- İyileştirme yaparken elinizin altındaki araçları kullanmayı ihmal etmeyin. Genel analiz için YSlow'u, resim birleştirme için SpriteMe'yi, farklı iyileştirme programlarınının kendi betikleriniz üzerindeki başarısını karşılaştırmak için de CompressorRater'i kullanabilirsiniz. İlk iki uygulamayı Steve Souders'ın geliştirdiğini de belirteyim.
Telvee Deneyi
Telvee) için başlangıçta performansı hiç düşünmemiştim. Çok sayıda CSS dosyası ve yine çok sayıda resim yükleniyordu. İyileştirmelerden önce aldığım ölçümler aşağıdaki gibiydi:
İstek # Veri boyutu (KB) Anasayfa 25 ~85 Fincan Detay 48 ~80
Daha sonra projeye django_compressor'u ekledim ve gerekli ayarlamaları yaptım. Hem JavaScript hem de CSS için YUI Compressor'u kullandım. Sprite'ları elle hazırlayıp, CSS dosyalarında gerekli değişiklikleri yaptım1. Daha sonra değişiklikleri sunucuya yükleyip tekrar ölçtüm:
İstek # Veri boyutu (KB) Anasayfa 12 ~70 (~160) Fincan Detay 14 ~64
Anasayfanın veri boyutu kolonunda yazan parantez içindeki değer gerçek sonuç. Ancak bu güncellemeyle anasayfanın tasarımı da değişti ve daha önce yüklenmeyen 90 KB'lık bir dosya eklendi. Bu nedenle sonucu 70 KB olarak kabul etmek yanlış olmayacaktır. İyileştirmelerin sonucu aşağıdaki gibi:
İstek # Veri boyutu (KB) Anasayfa %52 %17 Fincan Detay %70 %19
Django_compressor ve Data URI'ler
Christian Metts tarafından geliştirilen django_compressor yukarıda bahsettiğim iyileştirmeleri Django projelerinize kolayca uygulamanızı sağlıyor. Birkaç değişik çatalı birleştirip ufak eklemeler yaptığım depoya buradan ulaşabilirsiniz.
Bu depoda data-uri branşındaki compressor.filters.datauri.CssDataUriFilter filtresini kullanarak bağlantılı dosyalarınızı CSS dosyalarınızın içine gömebilirsiniz. Varsayılan ayarlara göre sadece 1024 Byte (1 KB) veya daha küçük boyuttaki dosyalar gömülecek, diğerleri bağlantılı olarak kalacaktır. COMPRESS_DATA_URI_MIN_SIZE ayarını kullanarak gömülecek dosyaların sınırını değiştirebilirsiniz.
Dosyalarınızı data: URI'lere dönüştürürken dikkat etmeniz gereken birkaç nokta var. Her şeyden önce dosya içeriği base64 kodlanıyor, yani veri boyutu yaklaşık üçte bir oranında artacaktır. Bant genişliği ile HTTP istek adedi arasındaki dengeyi düşünerek karar vermek size kalıyor2. Sorun yaratabilecek bir diğer şey; aynı dosyaya birden fazla kereler atıfta bulunulursa tüm dosya her seferinde tekrar tekrar gömülecektir. Bu sorunun çözümü tüm atıfları birleştirip tek bir bağlantıda toplamak3 ancak bunun da CSS dosyalarınızı tasnif ettiğiniz sistemi bozma ihtimali var.
Django_compressor'un Data: URI desteğini test edip, görüş ve önerilerinizi bana iletirseniz sevinirim. Eğer uygulamadıysanız yazıda belirttiğim teknikleri sitelerinize uygulamanızı tavsiye ederim. Özellikle, django_compressor sayesinde, Django projelerinde bu iyileştirmeleri yapmak çok basit. Sonuçta, teknoloji meraklıları olarak, performans artışının hoşunuza gideceğinden de eminim.
-----
1: İleride django_compressor'a sprite'ları otomatik oluşturma özelliğini eklemeyi düşünüyorum.
2: Modern Internet bağlantıları söz konusu olduğunda 1~2 KB'lık artışın karşılığında HTTP isteklerini bir azaltmak daha avantajlı görünüyor.