Web Performance Made Easy - Google I/O 2018 sürümü

Google IO 2018'de, web performansını iyileştirmeyi kolaylaştıran araç, kitaplık ve optimizasyon tekniklerinin bir özetini sunmuştuk. Burada, Oodles Theatre uygulamasını kullanarak hikayelerini açıklıyoruz. Ayrıca, tahmine dayalı yükleme ve yeni Guess.js girişimiyle ilgili denemelerimizden bahsedeceğiz.

Addy Osmani
Addy Osmani
Ewa Gasperowicz

Geçtiğimiz yıl, Web'i nasıl daha hızlı ve daha performanslı hale getirebileceğimizi bulmaya çalışmakla oldukça meşguldük. Bu, bu makalede sizinle paylaşmak istediğimiz yeni araçlar, yaklaşımlar ve kitaplıklara yol açtı. İlk bölümde, Oodles Theater uygulamasını geliştirirken pratikte kullandığımız bazı optimizasyon tekniklerini göstereceğiz. İkinci bölümde ise tahmini yükleme ve yeni Guess.js girişimiyle ilgili denemelerimizden bahsedeceğiz.

Performans ihtiyacı

İnternet her yıl daha da ağırlaşıyor. Web'in durumunu kontrol ettiğimizde, mobil cihazlarda ortalama bir sayfanın yaklaşık 1,5 MB ağırlığında olduğunu ve bunun büyük kısmının JavaScript ve resimlerden oluştuğunu görebiliriz.

Web sitelerinin büyümesi; ağ gecikmesi, CPU sınırlamaları, oluşturma engelleme kalıpları veya gereksiz üçüncü taraf kodları gibi diğer faktörlerle birlikte, karmaşık performans bulmacasına katkıda bulunur.

Çoğu kullanıcı, hızı, ihtiyaçlarıyla ilgili kullanıcı deneyimi hiyerarşisinin en üstünde olarak değerlendiriyor. Bu çok da şaşırtıcı değildir, çünkü bir sayfanın yüklenmesi tamamlanana kadar pek çok şey yapamazsınız. Sayfadan değer elde edemez, estetiğine hayran olamazsınız.

Kullanıcı deneyimi hiyerarşisi piramidi
Şekil 1. Hız, kullanıcılar için ne kadar önemli? (Speed Matters, Vol. 3)

Performansın kullanıcılar için önemli olduğunu biliyoruz. Ancak optimizasyona nereden başlayacağınızı keşfetmek bir sır gibi gelebilir. Neyse ki bu süreçte size yardımcı olabilecek araçlar var.

Lighthouse: Performans iş akışı için temel

Lighthouse, Chrome Geliştirici Araçları'nın bir parçasıdır. Web sitenizi denetlemenize olanak tanır ve sitenizi nasıl iyileştireceğiniz konusunda ipuçları verir.

Kısa süre önce, günlük geliştirme iş akışında gerçekten faydalı olan bir dizi yeni performans denetimi kullanıma sunduk.

Yeni Lighthouse denetimleri
Şek. 2. Yeni Lighthouse denetimleri

Bu özelliklerden nasıl yararlanabileceğinizi pratik bir örnekle inceleyelim: Oodles Theater uygulaması. Bu küçük demo web uygulamasında, en sevdiğimiz etkileşimli Google Doodles'lardan bazılarını deneyebilir ve hatta birkaç oyun oynayabilirsiniz.

Uygulamayı geliştirirken mümkün olduğunca yüksek performanslı olmasını sağlamak istedik. Optimizasyonun başlangıç noktası bir Lighthouse raporudur.

Oodles uygulaması için Lighthouse raporu
Şekil 3. Oodles uygulaması için Lighthouse raporu

Lighthouse raporunda görüldüğü üzere, uygulamamızın ilk performansı oldukça kötüydü. 3G ağında, kullanıcının ilk anlamlı boya için veya uygulamanın etkileşimli hale gelmesi için 15 saniye beklemesi gerekiyordu. Lighthouse, sitemizdeki birçok sorunu vurguladı ve 23 olan genel performans puanı da bunu tam olarak yansıtıyordu.

Sayfanın boyutu yaklaşık 3,4 MB olduğundan, bazı gereksiz öğeleri kaldırmamız gerekiyordu.

İlk performans görevimiz, genel deneyimi etkilemeden kolayca kaldırabileceğimiz özellikleri bulmaktı.

Performans optimizasyonu fırsatları

Gereksiz kaynakları kaldırın

Güvenle kaldırılabilecek bazı belirgin öğeler vardır: Boşluklar ve yorumlar.

Küçültmeden elde edilen kazanımlar
Şekil 4. JavaScript ve CSS'yi küçültme ve sıkıştırma

Lighthouse, Sıkıştırılmamış CSS ve JavaScript denetiminde bu fırsatı vurgular. Derleme sürecimiz için webpack kullanıyorduk. Bu nedenle, küçültme işlemini yapmak için Uglify JS eklentisini kullandık.

Kod sıkıştırma yaygın bir işlem olduğundan, kullandığınız derleme işlemi için hazır bir çözüm bulabilirsiniz.

Bu alandaki yararlı bir diğer denetim de Metin sıkıştırmayı etkinleştirme işlemidir. Sıkıştırılmamış dosyalar göndermenin bir anlamı yoktur ve CDN'lerin çoğu bu özelliği artık varsayılan olarak desteklemektedir.

Kodumuzu barındırmak için Firebase Hosting'i kullanıyorduk ve Firebase varsayılan olarak gzip sıkıştırmasını etkinleştiriyordu. Bu nedenle, kodumuzu makul bir CDN'de barındırdığımız için bu özelliği ücretsiz olarak elde ettik.

gzip çok popüler bir sıkıştırma yöntemi olsa da Zopfli ve Brotli gibi diğer mekanizmalar da ilgi görmeye başladı. Brotli, çoğu tarayıcıda destekleniyor. Öğelerinizi sunucuya göndermeden önce önceden sıkıştırmak için bir ikili dosya kullanabilirsiniz.

Verimli önbellek politikaları kullanın

Sonraki adımımız, gereksiz olduğunda kaynakları iki kez göndermemeyi sağlamaktı.

Lighthouse'daki Verimsiz önbellek politikası denetimi, tam olarak bunu başarmak için önbelleğe alma stratejilerimizi optimize edebileceğimizi fark etmemize yardımcı oldu. Sunucumuzda bir maksimum yaş geçerlilik süresi üst bilgisi ayarlayarak, tekrarlanan ziyarette kullanıcının daha önce indirdiği kaynakları yeniden kullanabilmesini sağladık.

İdeal olarak, mümkün olduğunca çok kaynağı mümkün olan en uzun süre boyunca mümkün olduğunca güvenli bir şekilde önbelleğe almayı ve güncellenen kaynakların verimli bir şekilde yeniden doğrulanması için doğrulama jetonları sağlamayı hedeflemeniz gerekir.

Kullanılmayan kodları kaldırın

Şimdiye kadar gereksiz indirme işleminin belirgin olan kısımlarını kaldırdık. Peki daha az belirgin olan kısımlar ne olacak? Örneğin, kullanılmayan kod.

Geliştirici Araçları'nda kod kapsamı
Şekil 5. Kod kapsamını kontrol edin

Bazen uygulamalarımıza gerçekten gerekli olmayan kodlar ekleriz. Bu durum özellikle uygulamanız üzerinde uzun süre çalışırsanız, ekibiniz veya bağımlılıklarınızda değişiklik olursa ve bazen de sahipsiz bir kitaplık bırakılırsa ortaya çıkar. Tam olarak bizim de başımıza gelen bu.

Başlangıçta uygulamamızın prototipini hızlıca oluşturmak için Material Components kitaplığını kullanıyorduk. Zamanla daha özel bir görünüme ve tarza geçtik ve bu kitaplığı tamamen unuttuk. Neyse ki kod kapsamı kontrolü, bu kodu paketimizde yeniden keşfetmemize yardımcı oldu.

Hem çalışma zamanı hem de uygulamanızın yükleme süresi için kod kapsamı istatistiklerinizi DevTools'da kontrol edebilirsiniz. Alttaki ekran görüntüsünde iki büyük kırmızı şerit görebilirsiniz. CSS'mizin %95'inden fazlası ve çok sayıda JavaScript kullanılmamıştı.

Lighthouse, kullanılmayan CSS kuralları denetiminde de bu sorunu tespit etti. 400 KB'dan fazla potansiyel tasarruf sağladığını gösterdi. Bu nedenle, kodumuza geri döndük ve söz konusu kitaplığın hem JavaScript hem de CSS bölümünü kaldırdık.

MVC bağdaştırıcısı kaldırılırsa stillerimiz 10 KB'a düşer
Şekil 6. MVC bağdaştırıcısını kaldırırsak stillerimiz 10 KB'a düşer.

Bu da CSS paketimizi 20 kat azalttı. Bu da iki satırlık ufak bir kayıt için gayet iyi bir fırsat.

Bu, performans puanımızın yükselmesine ve etkileşime geçme süresinin çok daha iyi hale gelmesine neden oldu.

Ancak bunun gibi değişiklikler söz konusu olduğunda tek başına metriklerinizi ve puanlarınızı kontrol etmek yeterli olmaz. Gerçek kodu kaldırmak hiçbir zaman risksiz değildir. Bu nedenle, her zaman olası gerilemelere dikkat etmeniz gerekir.

Kodumuzun %95'i kullanılmadığından bu% 5'lik kısmı hâlâ bir yerlerde var. Görünüşe göre bileşenlerimizden biri hâlâ bu kitaplıktaki stilleri (karalama slaytındaki küçük oklar) kullanıyordu. Ancak bu değişiklik çok küçük olduğu için bu stilleri düğmelere manuel olarak geri dahil edebildik.

Kitaplık eksik olduğu için düğmeler bozuldu
Şekil 7. Bir bileşen hâlâ kaldırılan kitaplığı kullanıyordu

Bu nedenle, kod kaldırırsanız olası görsel gerilemelere karşı korunmanıza yardımcı olacak uygun bir test iş akışını kullandığınızdan emin olun.

Çok büyük ağ yüklerinden kaçının

Büyük kaynakların web sayfası yüklemelerini yavaşlatabileceğini biliyoruz. Bu tür içerikler kullanıcılarımıza para kaybettirebilir ve veri planlarını büyük ölçüde etkileyebilir. Bu nedenle, bu tür içeriklere dikkat etmeniz çok önemlidir.

Lighthouse, Çok büyük ağ yükü denetimini kullanarak ağ yüklerimizden bazılarıyla ilgili bir sorun yaşadığımızı tespit etti.

Çok büyük ağ yüklerini tespit edin
Şekil 8. Çok büyük ağ yüklerini algılama

Burada, 3 MB'dan fazla kod gönderdiğimizi gördük. Bu, özellikle mobil cihazlarda oldukça fazla bir değer.

Bu listenin en başında, Lighthouse, 2 MB sıkıştırılmamış koddan oluşan bir JavaScript tedarikçi paketimizin olduğunu vurguladı. Bu, webpack tarafından da vurgulanan bir sorundur.

Ne demişler? En hızlı istek, hiç yapılmayan istektir.

İdeal olarak, kullanıcılarınıza sunduğunuz her bir öğenin değerini, bu öğelerin performansını ölçmeli ve ilk deneyimle birlikte sunmanın gerçekten de değerli olup olmadığına karar vermelisiniz. Çünkü bazen bu öğeler ertelenebilir, geç yüklenebilir veya boştayken işlenebilir.

Bizim örneğimizde, çok sayıda JavaScript paketiyle karşılaştığımız için çok şanslıydık çünkü JavaScript topluluğu, zengin bir JavaScript paketi denetleme araçları setine sahip.

JavaScript paketi denetimi
Şek. 9. JavaScript paketi denetimi

Webpack bundle analyzer ile başladık. Bu araç, unicode adlı bir bağımlılık eklediğimizi bildirdi. Bu bağımlılık, ayrıştırılmış 1,6 MB JavaScript olduğundan oldukça büyüktü.

Daha sonra editörümüze gittik ve Görsel Kod İçin Maliyet İçe Aktarma Eklentisi'ni kullanarak içe aktardığımız her modülün maliyetini görselleştirebildik. Bu, hangi bileşenin bu modüle referans veren kod içerdiğini keşfetmemizi sağladı.

Bunun üzerine BundlePhobia adlı başka bir araca geçiş yaptık. Bu araç, herhangi bir NPM paketinin adını girip sıkıştırılmış ve sıkıştırılmamış boyutunun ne kadar olduğunu tahmin etmenizi sağlar. Kullandığımız sümüklü böcek modülü için yalnızca 2, 2 kb ağırlığında güzel bir alternatif bulduk ve bunu değiştirdik.

Bu durum performansımızı büyük ölçüde etkiledi. Bu değişiklik ile JavaScript paketimizin boyutunu küçültecek diğer fırsatları keşfetmek arasında 2, 1 MB tasarruf ettik.

Bu paketlerin sıkıştırılmış ve küçültülmüş boyutunu hesaba kattığımızda, genel olarak %65 oranında iyileştirme elde ettik. Bu sürecin gerçekten de yapılmasına değer olduğunu gördük.

Bu nedenle, genel olarak sitelerinizde ve uygulamalarınızda gereksiz indirmeleri ortadan kaldırmaya çalışın. Öğelerinizin envanterini çıkarmak ve performans üzerindeki etkilerini ölçmek gerçekten büyük bir fark yaratabilir. Bu nedenle, öğelerinizi düzenli olarak denetlediğinizden emin olun.

Kod bölmeyle JavaScript'in açılış süresini kısaltma

Büyük ağ yükü, uygulamamızı büyük ölçüde etkileyebilir. Ancak JavaScript de uygulamanızı büyük ölçüde etkileyebilir.

JavaScript, en pahalı öğenizdir. Mobil cihazlarda büyük JavaScript paketleri gönderiyorsanız kullanıcılarınızın kullanıcı arayüzü bileşenlerinizle etkileşim kurması gecikebilir. Yani kullanıcılar, anlamlı bir şey gerçekleşmeden kullanıcı arayüzüne dokunabilir. Bu nedenle, JavaScript'in neden bu kadar pahalı olduğunu anlamamız önemlidir.

Tarayıcılar JavaScript'i bu şekilde işler.

JavaScript işleme
Şekil 10. JavaScript işleme

Öncelikle bu komut dosyasını indirmemiz gerekiyor. Ardından, bu kodu ayrıştırması, derlemesi ve yürütmesi gereken bir JavaScript motorumuz var.

Bu aşamalar, masaüstü bilgisayar veya dizüstü bilgisayar gibi ileri teknoloji cihazlarda, hatta ileri teknoloji telefonlarda çok fazla zaman almaz. Ancak ortalama bir cep telefonunda bu işlem beş ila on kat daha uzun sürebilir. Etkileşimi geciktirmenin nedeni budur. Bu nedenle, bu boyutu azaltmayı denememiz önemlidir.

Uygulamanızdaki bu sorunları keşfetmenize yardımcı olmak için Lighthouse'a yeni bir JavaScript başlatma süresi denetimi ekledik.

JavaScript'in açılış süresi
Şekil 11. JavaScript başlatma süresi denetimi

Oodle uygulamasında ise JavaScript'in başlatılması 1,8 saniye sürdüğünü öğrendik. Tüm rotalarımızı ve bileşenlerimizi tek bir monolitik JavaScript paketine statik olarak içe aktarıyorduk.

Bu sorunun üstesinden gelmenin bir yolu kod bölme işlemini kullanmaktır.

Kod bölme işlemi pizzaya benzer

Kod bölme, kullanıcılarınıza bir pizza değerinde JavaScript yerine, ihtiyaç duydukları anda tek seferde yalnızca bir dilim JavaScript vermeyi ifade eder.

Kod bölme, rota veya bileşen düzeyinde uygulanabilir. React ve React Loadable, Vue.js, Angular, Polymer, Preact ve diğer birçok kitaplıkla mükemmel çalışır.

Uygulamamıza kod bölme özelliğini dahil ettik, statik içe aktarmalardan dinamik içe aktarmalara geçtik. Böylece, gerektiğinde kodu eşzamansız olarak gecikmeli olarak yükleyebildik.

Dinamik içe aktarmayla kod bölme
Şekil 13. Dinamik içe aktarmalarla kod bölme

Bunun etkisi hem paketlerimizin boyutunu küçülttü hem de JavaScript'in başlatma süresini azalttı. Bu sayede uygulamanın süresi 0,78 saniyeye indirilerek %56 daha hızlı hale getirildi.

Genel olarak, JavaScript yoğun bir deneyim oluşturuyorsanız kodu yalnızca ihtiyaç duyduğu kullanıcıya gönderdiğinizden emin olun.

Kod bölme gibi kavramlardan yararlanın, ağaç sallama gibi fikirleri keşfedin ve webpack kullanıyorsanız kitaplığınız boyutunu nasıl küçülteceğinizle ilgili birkaç fikir için webpack-libs-optimizations reposuna göz atın.

Resimleri optimize edin

Resim yükleme performansı şakası

Oodle uygulamasında çok fazla resim kullanıyoruz. Maalesef Lighthouse, bu konuda hiç istekli değildi. Aslında, resimle ilgili üç denetimin de başarısız olduğunu görüyoruz.

Resimlerimizi optimize etmeyi unutmuştuk, doğru boyutlarda ayarlamıyorduk ve diğer resim biçimlerini kullanmaktan da bazı kazanımlar elde edebiliriz.

Resim denetimleri
Şekil 14. Lighthouse resim denetimleri

Resimlerimizi optimize etmekle işe başladık.

Tek seferlik optimizasyon turu için ImageOptim veya XNConvert gibi görsel araçları kullanabilirsiniz.

Daha otomatik bir yaklaşım, derleme sürecinize imagemin gibi kitaplıklarla bir resim optimizasyonu adımı eklemektir.

Böylece, gelecekte eklenecek resimlerin otomatik olarak optimize edilmesini sağlayabilirsiniz. Akamai gibi bazı CDN'ler veya Cloudinary, Fastly ya da Uploadcare gibi üçüncü taraf çözümler size kapsamlı resim optimizasyon çözümleri sunar. Böylece resimlerinizi bu hizmetlerde barındırabilirsiniz.

Maliyet veya gecikme sorunları nedeniyle bunu yapmak istemiyorsanız Thumbor veya Imageflow gibi projeler kendi kendine barındırılan alternatifler sunar.

Optimizasyondan önce ve sonra
Şekil 15. Optimizasyondan önce ve sonra

Arka plan PNG'miz webpack'te büyük olarak işaretlendi ve haklı olarak da öyleydi. Görüntüleme alanına uygun şekilde boyutlandırdıktan ve ImageOptim üzerinden çalıştırdıktan sonra 100 KB'a düşürdük. Bu kabul edilebilir bir boyut.

Bu işlemi sitemizdeki birden fazla resim için tekrarlayarak genel sayfa ağırlığını önemli ölçüde düşürebildik.

Animasyonlu içerik için doğru biçimi kullanın

GIF'ler çok pahalı olabilir. Şaşırtıcı bir şekilde, GIF biçimi hiçbir zaman animasyon platformu olarak tasarlanmamıştı. Bu nedenle, daha uygun bir video biçimine geçmek dosya boyutu açısından size büyük tasarruflar sağlar.

Oodle uygulamasında, ana sayfada giriş dizisi olarak bir GIF kullanıyorduk. Lighthouse'a göre, daha verimli bir video biçimine geçerek 7 MB'dan fazla tasarruf edebiliriz. 7,3 MB ağırlığındaki klibimiz, makul herhangi bir web sitesi için çok fazla olduğundan bunun yerine, daha geniş tarayıcı desteği için bir mp4 ve WebM olmak üzere iki kaynak dosyasına sahip bir video öğesine dönüştürdük.

Animasyonlu GIF'leri video ile değiştirin
Şekil 16. Animasyonlu GIF'leri videoyla değiştirme

Animasyon GIF'imizi mp4 dosyasına dönüştürmek için FFmpeg aracını kullandık. WebM biçimi size daha da büyük tasarruflar sunar. ImageOptim API bu dönüştürme işlemini sizin için yapabilir.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

Bu dönüşüm sayesinde toplam ağırlığımızın %80'inden fazlasını azaltmayı başardık. Bu da bizi yaklaşık 1 MB'a düşürdü.

Yine de 1 MB, özellikle bant genişliği kısıtlı bir kullanıcı için ağ üzerinden aktarılacak büyük bir kaynaktır. Neyse ki Effective Type API'yi kullanarak bunların yavaş bir bant genişliğinde olduğunu fark edip çok daha küçük bir JPEG verebiliriz.

Bu arayüz, kullanıcının kullandığı ağ türünü tahmin etmek için etkili gidiş dönüş süresini ve azaltma değerlerini kullanır. Yavaş 2G, 2G, 3G veya 4G gibi bir dize döndürür. Dolayısıyla bu değere bağlı olarak, kullanıcı 4G'nin altındaysa video öğesini resimle değiştirebiliriz.

if (navigator.connection.effectiveType) { ... }

Bu, deneyimden biraz uzaklaşmanıza neden olsa da en azından site yavaş bir bağlantıda kullanılabilir.

Ekran dışındaki resimleri geç yükleme

Kullanıcı bunları sayfada doğrudan göremese bile bantlar, kaydırma çubukları veya çok uzun sayfalar genellikle resimleri yükler.

Lighthouse, ekran dışı resimler denetiminde bu davranışı işaretler. Bu davranışı DevTools'un ağ panelinde de görebilirsiniz. Sayfada yalnızca birkaç resim görünürken çok sayıda resim geldiğini görüyorsanız bunları yavaş yüklemeyi tercih edebilirsiniz.

Yavaş yükleme henüz tarayıcıda doğal olarak desteklenmediğinden bu özelliği eklemek için JavaScript'i kullanmamız gerekiyor. Oodle kapaklarımıza gecikmeli yükleme davranışı eklemek için Lazysizes kitaplığını kullandık.

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysizes, yalnızca öğenin görünürlük değişikliklerini izlemekle kalmayıp optimum kullanıcı deneyimi için görüntüye yakın öğeleri proaktif olarak önceden getirmesi nedeniyle akıllıdır. Ayrıca, IntersectionObserver ile isteğe bağlı entegrasyon sunar. Bu entegrasyon, çok verimli görünürlük aramaları yapmanızı sağlar.

Bu değişiklikten sonra resimlerimiz isteğe bağlı olarak getiriliyor. Bu konuyu daha ayrıntılı incelemek isterseniz çok kullanışlı ve kapsamlı bir kaynak olan images.guide sitesine göz atın.

Tarayıcıya kritik kaynakları erken yayınlamasına yardımcı olun

Kablo üzerinden tarayıcıya gönderilen her bayt aynı önem derecesine sahip değildir ve tarayıcı bunu bilir. Birçok tarayıcı, önce neleri getirmeleri gerektiğine karar vermek için sezgisel yöntemlere sahiptir. Bu nedenle, bazen resimlerden veya komut dosyalarından önce CSS'yi getirirler.

Sayfanın yazarları olarak, tarayıcıya bizim için gerçekten önemli olanları bildirmemiz yararlı olabilir. Neyse ki, tarayıcı tedarikçileri son birkaç yılda bu konuda bize yardımcı olacak çeşitli özellikler ekliyor. Örneğin link rel=preconnect, preload veya prefetch gibi kaynak ipuçlarından yararlanıyoruz.

Web platformuna getirilen bu özellikler, tarayıcının doğru zamanda doğru öğeyi getirmesine yardımcı olur ve bunun yerine komut dosyası kullanılarak yapılan özel yükleme, mantık tabanlı yaklaşımların bazılarına göre biraz daha verimli olabilir.

Lighthouse'ın bu özelliklerin bazılarını etkili bir şekilde kullanma konusunda bize nasıl rehberlik ettiğini görelim.

Lighthouse'un bize önerdiği ilk şey, herhangi bir kalkış noktasına yönelik maliyetli gidiş dönüş yolculuklarından kaçınmak.

Herhangi bir kalkış noktasına birden fazla, maliyetli gidiş dönüşten kaçının
Şekil 17. Herhangi bir kaynak için birden fazla, maliyetli gidiş dönüş yolculuğundan kaçının

Oodle uygulamasında aslında Google Fonts'u yoğun bir şekilde kullanıyoruz. Sayfanıza bir Google Yazı Tipi stil sayfası eklediğinizde bu sayfa iki alt alan adına bağlanır. Lighthouse, bu bağlantıyı ısıtabilseydik ilk bağlantı süremizde 300 milisaniyeye kadar tasarruf edebileceğimizi söylüyor.

link rel ön bağlantısından yararlanarak bu bağlantı gecikmesini etkili bir şekilde maskeleyebilir.

Özellikle yazı tipi CSS'mizin googleapis.com'da, yazı tipi kaynaklarımızın ise Gstatic'te barındırıldığı Google Yazı Tipleri gibi durumlarda bu durum çok büyük bir etki yaratabilir. Bu nedenle, bu optimizasyonu uyguladık ve birkaç yüz milisaniye azalttık.

Lighthouse'ın önerdiği bir sonraki adım, önemli isteklerini önceden yüklemektir.

Önemli istekleri önceden yükle
Şek. 18. Önemli istekleri önceden yükleme

<link rel=preload> gerçekten güçlüdür. Tarayıcıyı mevcut gezinmenin bir parçası olarak bir kaynağa ihtiyaç duyduğunu bildirir ve tarayıcının kaynağı en kısa sürede getirmesini sağlamaya çalışır.

Burada Lighthouse, iki web yazı tipi yüklediğimiz için temel web yazı tipi kaynaklarımızı önceden yüklememiz gerektiğini söylüyor.

Web yazı tipinde ön yükleme şu şekilde yapılır: rel=preload'yi belirtirsiniz, yazı tipi türüyle birlikte as'yi iletirsiniz ve ardından yüklemeye çalıştığınız yazı tipi türünü (ör. woff2) belirtirsiniz.

Bunun sayfanız üzerindeki etkisi oldukça büyüktür.

Kaynakları önceden yüklemenin etkisi
Şek. 19. Kaynakları önceden yüklemenin etkisi

Normalde, bağlantı rel ön yükleme kullanılmıyorsa ve web yazı tipleri sayfanız için kritik öneme sahipse tarayıcı öncelikle HTML'nizi getirmeli, CSS'nizi ayrıştırmalı ve daha sonra web yazı tiplerinizi getirmelidir.

Bağlantı rel preload'ı kullanarak tarayıcı, HTML'nizi ayrıştırır ayrıştırmaz bu web yazı tiplerini çok daha erken getirmeye başlayabilir. Uygulamamız söz konusu olduğunda, bu sayede web yazı tiplerimizi kullanarak metin oluşturma işlemini bir saniye daha kısa sürede tamamlayabildik.

Google Fonts'u kullanarak yazı tiplerini önceden yüklemeyi deneyecekseniz bu işlem o kadar basit değildir.

Stil sayfalarımızdaki yazı tipi yüzlerimizde belirttiğimiz Google yazı tipi URL'leri, yazı tipi ekibinin oldukça düzenli olarak güncellediği bir şeydi. Bu URL'lerin süresi dolabilir veya düzenli olarak güncellenebilir. Bu nedenle, yazı tipi yükleme deneyiminiz üzerinde tam kontrol sahibi olmak istiyorsanız web yazı tiplerinizi kendiniz barındırmanızı öneririz. Bu özellik çok kullanışlı olabilir, çünkü bağlantı rel önceden yüklemesi gibi öğelere erişmenizi sağlar.

Bizim durumumuzda, Google Web Yazı Tipleri Yardımcı aracının bu web yazı tiplerinden bazılarını çevrimdışı hale getirmemize ve yerel olarak ayarlamamıza yardımcı olması açısından çok faydalı olduğunu gördük. Bu aracı denemenizi öneririz.

Kritik kaynaklarınız kapsamında web yazı tipleri kullanıyorsanız veya JavaScript kullanıyorsanız tarayıcıya kritik kaynaklarınızı bir an önce sunmasına yardımcı olmaya çalışın.

Deneysel: Öncelikli İpuçları

Bugün sizinle paylaşmak istediğimiz özel bir şey var. Önceden yüklemenin yanı sıra kaynak ipuçları gibi özelliklerin yanı sıra, öncelik ipuçları adını verdiğimiz yepyeni bir deneysel tarayıcı özelliği üzerinde de çalışıyoruz.

İlk olarak görünen içeriğin önceliğini ayarlama
Şekil 20. Öncelik ipuçları

Bu, tarayıcıya bir kaynağın ne kadar önemli olduğunu ima etmenize olanak tanıyan yeni bir özelliktir. Düşük, yüksek veya otomatik değerlerine sahip yeni bir özellik (önem) gösterir.

Bu sayede, önemli olmayan kaynakların (ör. kritik olmayan stiller, resimler veya fetch API çağrıları) önceliğini düşürerek anlaşmazlıkları azaltabiliriz. Ayrıca, hero resimlerimiz gibi daha önemli öğelerin önceliğini de artırabiliriz.

Oodle uygulamamız söz konusu olduğunda bu, optimize edebileceğimiz pratik bir yere sahip olmamızı sağladı.

İlk olarak görünen içeriğin önceliğini ayarlama
Şekil 21. Başlangıçta görünen içerik için öncelik ayarlama

Resimlerimize gecikmeli yükleme özelliğini eklemeden önce, tarayıcı tüm karalamalarımıza sahip olan bir resim bandına sahipti ve tarayıcı, bandın en başındaki tüm resimleri yüksek öncelikli olarak getiriyordu. Maalesef kullanıcı için en önemli olan bantın ortasındaki resimlerdi. Bu nedenle, arka plan resimlerinin önemini çok düşük, ön plan resimlerinin önemini ise çok yüksek olarak belirledik. Bu, yavaş 3G'de iki saniyelik bir etki ve bu resimleri ne kadar hızlı alıp oluşturabildiğimizi etkiledi. Yani güzel ve olumlu bir deneyim.

Bu özelliği birkaç hafta içinde Canary'de kullanıma sunmayı umuyoruz. Gözünüz bizde olsun.

Web yazı tipi yükleme stratejiniz olmalıdır.

İyi bir tasarımın temelinde yazı tipi vardır. Web yazı tipleri kullanıyorsanız metninizin oluşturulmasını engellemek istemezsiniz ve kesinlikle görünmez metin göstermek istemezsiniz.

Bu durumu artık Lighthouse'ta web yazı tipleri yüklenirken görünmez metin kullanmaktan kaçının denetimiyle vurguluyoruz.

Web yazı tipleri yüklenirken görünmez metinlerden kaçının
Şekil 22. Web yazı tipleri yüklenirken görünmez metin kullanmaktan kaçının

Web yazı tiplerinizi bir yazı tipi yüzü bloğu kullanarak yüklerseniz söz konusu web yazı tipinin getirilmesi uzun sürerse ne yapılacağına tarayıcı karar verir. Bazı tarayıcılar, sistem yazı tipine geçmeden önce bu işlem için üç saniyeye kadar bekler ve indirilen yazı tipiyle değiştirir.

Bu görünmez metinden kaçınmaya çalışıyoruz. Bu yüzden, bu durumda web yazı tipi çok uzun olsaydı bu haftanın klasik doodle'larını göremeyecektik. Neyse ki font-display adlı yeni bir özellik sayesinde bu süreç üzerinde çok daha fazla kontrole sahipsiniz.

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

Yazı tipi görüntüleme, web yazı tiplerinin nasıl oluşturulacağına veya değiştirilmelerinin ne kadar sürdüğüne göre yedek yazı tipinin nasıl kullanılacağına karar vermenize yardımcı olur.

Bu örnekte yazı tipi görüntüleme değişimini kullanıyoruz. Değiştirme işlemi, yazı tipi yüzü için sıfır saniyelik bir engelleme süresi ve bir sonsuz değiştirme süresi sağlar. Bu, yazı tipinin yüklenmesi biraz zaman alırsa tarayıcının metninizi hemen yedek yazı tipiyle çizeceği anlamına gelir. Yazı tipi kullanılabilir olduğunda bunu değiştirecektir.

Uygulamamız söz konusu olduğunda bu, çok erken bir aşamada anlamlı metinler göstermemize ve hazır olduğunda web yazı tipine geçiş yapmamıza olanak tanıdığı için çok faydalı oldu.

Yazı tipi görüntüleme sonucu
Şekil 23. Yazı tipi görüntüleme sonucu

Genel olarak, web'in büyük bir yüzdesi gibi web yazı tipleri kullanıyorsanız iyi bir web yazı tipi yükleme stratejiniz olmalıdır.

Yazı tipi yükleme deneyiminizi optimize etmek için kullanabileceğiniz birçok web platformu özelliği vardır. Bununla birlikte, Zach Leatherman'ın Web Font Recipes (Web Yazı Tipi Tarifleri) deposuna da göz atın. Bu depo gerçekten çok kullanışlıdır.

Oluşturmayı engelleyen komut dosyalarını azaltma

Uygulamamızın, en azından bazı temel kullanıcı deneyimlerini biraz daha erken sunmak için indirme zincirinin daha başlarında yayınlayabileceğimiz başka bölümleri de var.

Lighthouse zaman çizelgesi şeridinde, tüm kaynakların yüklendiği bu ilk birkaç saniyede kullanıcının aslında herhangi bir içerik göremediğini görebilirsiniz.

Oluşturmayı engelleyen stil sayfası fırsatını azaltma
Şek. 24. Oluşturmayı engelleyen stil sayfası fırsatlarını azaltma

Harici stil sayfalarını indirip işlememiz, oluşturma sürecimizin ilerleme kaydetmesini engelliyor.

Stillerden bazılarını daha erken sunarak kritik oluşturma yolumuzu optimize etmeye çalışabiliriz.

Bu ilk oluşturma işleminden sorumlu stilleri ayıklayıp HTML'mize satır içi olarak eklersek tarayıcı, harici stil sayfalarının gelmesini beklemeden bunları hemen oluşturabilir.

Bizim durumumuzda, kritik içeriğimizi bir derleme adımı sırasında index.html dosyasına satır içi yapmak için Critical adlı bir NPM modülü kullandık.

İşin büyük bir kısmını bu modül yapsa da bunun farklı rotalarda sorunsuz bir şekilde çalışmasını sağlamak biraz zordu.

Dikkatli olmazsanız veya sitenizin yapısı gerçekten karmaşıksa ve en baştan uygulama kabuğu mimarisi planlamadıysanız bu tür bir kalıbı kullanmaya başlamak gerçekten zor olabilir.

Bu nedenle, performansla ilgili hususları erkenden dikkate almak çok önemlidir. Baştan itibaren performansı göz önünde bulundurarak tasarım yapmazsanız daha sonra performansla ilgili sorunlarla karşılaşma olasılığınız yüksektir.

Riskimiz sonunda karşılığını verdi. Bu yöntemi uygulamayı başardık ve uygulama çok daha erken içerik yayınlamaya başladı. Bu da ilk anlamlı gösterim süremizi önemli ölçüde iyileştirdi.

Sonuç

Bu, sitemize uyguladığımız performans optimizasyonlarının uzun bir listesiydi. Sonuca bakalım. Uygulamamız, optimizasyondan önce ve sonra, 3G ağ üzerinde orta düzeyde bir mobil cihaza bu şekilde yüklendi.

Lighthouse performans puanı 23'ten 91'e yükseldi. Hız açısından oldukça iyi bir ilerleme kaydettiniz. Tüm değişiklikler, Lighthouse raporunu sürekli olarak kontrol etmemiz ve takip etmemiz sayesinde sağlandı. Tüm iyileştirmeleri teknik olarak nasıl uyguladığımıza göz atmak isterseniz depomuza, özellikle de bu depomuza gelen halkla ilişkilere göz atabilirsiniz.

Tahmini performans: Veriye dayalı kullanıcı deneyimleri

Makine öğreniminin birçok alanda gelecek için heyecan verici bir fırsat sunduğunu düşünüyoruz. Gelecekte daha fazla deneme yapılmasını umduğumuz fikirlerden biri, gerçek verilerin oluşturduğumuz kullanıcı deneyimlerini gerçekten yönlendirebileceğidir.

Günümüzde, kullanıcının ne isteyebileceği veya neye ihtiyaç duyabileceği ve dolayısıyla nelerin önceden getirilmeye, önceden yüklenmeye veya önceden önbelleğe alınmaya değer olduğu konusunda birçok keyfi karar alıyoruz. Doğru tahmin edersek az miktarda kaynağa öncelik verebiliriz ancak bunu web sitesinin tamamına ölçeklendirmek gerçekten zordur.

Artık optimizasyonlarımızı daha iyi bilgilendirmek için kullanabileceğimiz verilere sahibiz. Google Analytics Reporting API'yi kullanarak, sitemizdeki herhangi bir URL'nin bir sonraki en üst sayfasına ve çıkış yüzdelerine bakabilir, böylece hangi kaynaklara öncelik vermemiz gerektiğine dair sonuçlara varabiliriz.

Bunu iyi bir olasılık modeliyle birleştirirsek içeriği agresif bir şekilde aşırı ön besleyerek kullanıcılarımızın verilerini israf etmekten kaçınabiliriz. Bu Google Analytics verilerinden ve bu modelleri uygulamak için Markov zincirleri veya nöral ağ gibi makine öğrenimi ve modelleri kullanabiliriz.

Web Uygulamaları için Veriye Dayalı Paketleme
Şek. 25. Web Uygulamaları için Veriye Dayalı Paketleme

Bu denemeleri kolaylaştırmak için Guess.js adını verdiğimiz yeni bir girişimi duyurmaktan memnuniyet duyuyoruz.

Guess.js
Şekil 26. Guess.js

Guess.js, web için veri odaklı kullanıcı deneyimlerine odaklanan bir projedir. Bu özelliğin, web performansını iyileştirmek ve daha da ötesine geçmek için verileri kullanmayı keşfetmenize ilham vereceğini umuyoruz. Bunların tümü açık kaynaklıdır ve şu anda GitHub'da kullanılabilir. Bu proje Minko Gechev, Gatsby'den Kyle Matthews, Katie Hempenius ve diğer birçok kişinin açık kaynak topluluğuyla birlikte geliştirildi.

Guess.js'ye göz atın ve ne düşündüğünüzü bize bildirin.

Özet

Puanlar ve metrikler, web'in hızını artırmada faydalıdır ancak bunlar hedefler değil, yalnızca araçlardır.

Hepimiz hareket halindeyken sayfaların yavaş yüklendiğini deneyimledik. Artık kullanıcılarımıza çok hızlı yüklenen, daha keyifli deneyimler sunma fırsatımız var.

Performansı iyileştirmek bir yolculuktur. Birçok küçük değişiklik büyük kazançlar sağlayabilir. Doğru optimizasyon araçlarını kullanarak ve Lighthouse raporlarını takip ederek kullanıcılarınıza daha iyi ve daha kapsayıcı bir deneyim sunabilirsiniz.

Özel teşekkürler: Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse ve Google Doodles.