Web Performansını Kolaylaştırma - Google I/O 2018 sürümü

Google IO 2018'de, web performansını iyileştirmeyi kolaylaştıran araçlar, kitaplıklar ve optimizasyon teknikleriyle ilgili bir özet sunduk. Bu yazıda, Oodles Theater uygulamasını kullanarak bu kavramları açıklıyoruz. Ayrıca, tahmini yükleme ve yeni Guess.js girişimi ile ilgili denemelerimizden de bahsediyoruz.

Ewa Gasperowicz

Geçtiğimiz yıl boyunca web'i nasıl daha hızlı ve daha iyi performans gösterecek şekilde hale getirebileceğimizi anlamak için yoğun bir şekilde çalıştık. Bu durum, bu makalede sizlerle paylaşmak istediğimiz yeni araçların, yaklaşımların ve kitaplıkların ortaya çıkmasına yol açtı. İlk bölümde, The 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 cihazlardaki ortalama bir sayfanın yaklaşık 1, 5 MB ağırlığında olduğunu ve bunun büyük bir kısmının JavaScript ve resimlerden oluştuğunu görüyoruz.

Web sitelerinin büyüyen boyutu, ağ gecikmesi, CPU sınırlamaları, oluşturmayı engelleyen kalıplar veya gereksiz üçüncü taraf kodu gibi diğer faktörlerle birlikte karmaşık performans bulmacasına katkıda bulunur.

Çoğu kullanıcı, hızı ihtiyaçlarının kullanıcı deneyimi hiyerarşisinde en üst sırada değerlendiriyor. Sayfa yüklenene kadar pek bir şey yapamayacağınız için bu durum pek de şaşırtıcı değildir. Sayfadan değer elde edemez, estetiğine hayran olamazsınız.

Kullanıcı deneyimi hiyerarşi piramidi
Şek. 1. Hız, kullanıcılar için ne kadar önemli? (Hız Önemlidir, Cilt 3)

Performansın kullanıcılar için önemli olduğunu biliyoruz ancak optimizasyona nereden başlayacağınızı bulmak da zor olabilir. 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 nasıl daha iyi hale getirebileceğ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 Doodle'larından bazılarını deneyebilir, hatta bir veya iki oyun oynayabilirsiniz.

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

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ı boyama için veya uygulamanın etkileşimli hale gelmesi için 15 saniye beklemesi gerekiyordu. Lighthouse, sitemizle ilgili bir sürü sorunu vurguladı ve genel performans puanı olan 23 de bunu tam olarak yansıtıyordu.

Sayfa yaklaşık 3,4 MB ağırlığındaydı.Bu nedenle, boyutu azaltmamız gerekiyordu.

Bu, ilk performans sorunumuzun başlangıcı oldu: Genel deneyimi etkilemeden kolayca kaldırabileceğimiz öğeleri bulmamız gerekiyordu.

Performans optimizasyonu fırsatları

Gereksiz kaynakları kaldırma

Boşluk ve yorumlar gibi bazı belirgin öğeler güvenle kaldırılabilir.

Küçültme işleminden elde edilen kazanımlar
Şek. 4. JavaScript ve CSS'yi küçültün ve sıkıştırın

Lighthouse, bu fırsatı Unminified CSS & JavaScript audit (Küçültülmemiş CSS ve JavaScript denetimi) bölümünde vurgular. Derleme sürecimizde webpack kullandığımız için küçültme işlemini gerçekleştirmek üzere Uglify JS eklentisini kullandık.

Küçültme yaygın bir görev olduğundan, kullandığınız derleme süreci için hazır bir çözüm bulabilirsiniz.

Bu alandaki bir diğer yararlı denetim de Metin sıkıştırmayı etkinleştirin'dir. Sıkıştırılmamış dosyalar göndermenin bir nedeni yoktur ve çoğu CDN bu özelliği günümüzde kutudan çıktığı gibi desteklemektedir.

Kodumuzu barındırmak için Firebase Hosting'i kullanıyorduk ve Firebase, gzipping'i varsayılan olarak etkinleştiriyor. Bu nedenle, kodumuzu makul bir CDN'de barındırarak 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 giderek daha fazla ilgi görüyor. Brotli, çoğu tarayıcıda desteklenir. Öğelerinizi sunucuya göndermeden önce önceden sıkıştırmak için ikili dosya kullanabilirsiniz.

Verimli önbellek politikaları kullanın

Bir sonraki adımımız, gereksizse kaynakları iki kez göndermemeyi sağlamaktı.

Lighthouse'taki 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 max-age geçerlilik süresi üstbilgisi ayarlayarak, kullanıcının tekrar ziyaret ettiğinde daha önce indirdiği kaynakları yeniden kullanabilmesini sağladık.

İdeal olarak, mümkün olduğunca çok sayıda kaynağı mümkün olduğunca uzun süre 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ı hedeflemelisiniz.

Kullanılmayan kodu kaldırma

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

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

Bazen uygulamalarımıza gerçekten gerekli olmayan kodlar ekleriz. Bu durum özellikle uygulamanız üzerinde uzun süre çalıştıysanız, ekibiniz veya bağımlılıklarınız değiştiyse ve bazen de bağımsız bir kitaplık geride kaldıysa yaşanır. Biz de tam olarak bunu yaşadık.

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üm ve hisse geçtik ve bu kitaplığı tamamen unuttuk. Neyse ki kod kapsamı kontrolü, bu sorunu paketimizde yeniden keşfetmemize yardımcı oldu.

Kod kapsamı istatistiklerinizi, uygulamanızın hem çalışma zamanı hem de yükleme süresi için DevTools'ta kontrol edebilirsiniz. Alttaki ekran görüntüsünde iki büyük kırmızı şeridi görebilirsiniz. CSS'mizin %95'inden fazlası ve büyük bir JavaScript grubu kullanılmıyordu.

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

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

Bu sayede CSS paketimiz 20 kat küçüldü. Bu, iki satırlık küçük bir commit için oldukça iyi bir sonuç.

Bu değişiklikler performans puanımızı yükseltti ve Etkileşim Süresi de önemli ölçüde iyileşti.

Ancak bu tür değişiklikler olduğunda yalnızca metriklerinizi ve puanlarınızı kontrol etmek yeterli değildir. Gerçek kodu kaldırmak hiçbir zaman risksiz değildir. Bu nedenle, her zaman olası gerilemelere karşı dikkatli olmalısınız.

Kodumuz %95 oranında kullanılmamıştı. Ancak% 5'lik bir kısım hâlâ bir yerlerde duruyordu. Görünüşe göre bileşenlerimizden biri (doodle kaydırıcısındaki küçük oklar) hâlâ bu kitaplıktaki stilleri kullanıyordu. Ancak bu değişiklik çok küçük olduğundan, stilleri düğmelere manuel olarak geri ekleyebildik.

Düğmeler, eksik kitaplık nedeniyle bozuldu
Şek. 7. Bir bileşen, kaldırılan kitaplığı kullanmaya devam ediyordu.

Bu nedenle, kodu kaldırırsanız olası görsel gerilemelere karşı korunmanıza yardımcı olacak uygun bir test iş akışınızın olduğundan 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 durum, kullanıcılarımızın para kaybetmesine ve veri planlarının büyük ölçüde etkilenmesine neden olabilir. Bu nedenle, bu konuya dikkat etmek çok önemlidir.

Lighthouse, Enormous network payload (Büyük ağ yükü) denetimini kullanarak ağ yüklerimizden bazılarında sorun olduğunu tespit edebildi.

Çok büyük ağ yüklerini algılama
Şek. 8. Çok büyük ağ yüklerini algılama

Burada, gönderilen kodun 3 MB'tan fazla olduğunu gördük. Bu, özellikle mobil cihazlarda oldukça fazla bir miktardır.

Bu listenin en üstünde Lighthouse, 2 MB sıkıştırılmamış kod içeren bir JavaScript satıcı paketimiz olduğunu vurguladı. Bu, webpack tarafından da vurgulanan bir sorundur.

En hızlı istek, yapılmayan istektir.

İdeal olarak, kullanıcılarınıza sunduğunuz her bir öğenin değerini ölçmeli, bu öğelerin performansını ölçmeli ve ilk deneyimle birlikte gönderilmeye değip değmeyeceğine karar vermelisiniz. Çünkü bu öğeler bazen ertelenebilir, geç yüklenir veya boşta kalma süresinde işlenebilir.

Bizim durumumuzda, çok sayıda JavaScript paketiyle uğraştığımız için JavaScript topluluğunun zengin bir JavaScript paketi denetleme araçları setine sahip olması sayesinde şanslıydık.

JavaScript paketi denetimi
Şekil 9. JavaScript paketi denetimi

Öncelikle, ayrıştırılmış JavaScript'in 1, 6 MB'ını oluşturan unicode adlı bir bağımlılığı dahil ettiğimizi bildiren webpack bundle analyzer ile başladık.

Ardından, düzenleyicimize geçtik ve Import Cost Plugin for Visual code'u kullanarak içe aktardığımız her modülün maliyetini görselleştirebildik. Bu sayede, hangi bileşenin bu modüle referans veren kodu içerdiğini keşfedebildik.

Ardından başka bir araca, BundlePhobia'ya geçtik. Bu araç, herhangi bir NPM paketinin adını girmenize ve küçültülmüş ve sıkıştırılmış boyutunun ne kadar olacağını görmenize olanak tanır. Kullandığımız slug modülüne alternatif olarak yalnızca 2, 2 KB ağırlığında bir modül bulduk ve bu modüle geçtik.

Bu durum, performansımızı büyük ölçüde etkiledi. Bu değişiklik ve JavaScript paket boyutunu küçültmek için diğer fırsatları keşfetmemiz sayesinde 2, 1 MB kod tasarrufu sağladık.

Bu paketlerin gzip ile sıkıştırılmış ve küçültülmüş boyutu dikkate alındığında genel olarak% 65 iyileşme gördük. Bunun bir süreç olarak gerçekten yapmaya 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 oluşturmak ve performans üzerindeki etkilerini ölçmek büyük bir fark yaratabilir. Bu nedenle, öğelerinizi düzenli olarak denetlediğinizden emin olun.

Kod bölme ile JavaScript başlatma süresini kısaltma

Büyük ağ yükleri uygulamamız üzerinde büyük bir etkiye sahip olsa da gerçekten büyük bir etkiye sahip olabilecek başka bir şey daha var: JavaScript.

JavaScript, en pahalı varlığınızdır. Mobil cihazlarda büyük JavaScript paketleri gönderiyorsanız kullanıcılarınızın kullanıcı arayüzü bileşenlerinizle etkileşime geçme süresi gecikebilir. Bu nedenle, kullanıcılar anlamlı bir işlem gerçekleşmeden kullanıcı arayüzüne dokunabilir. Bu nedenle, JavaScript'in neden bu kadar maliyetli olduğunu anlamamız önemlidir.

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

JavaScript işleme
Şek. 10. JavaScript işleme

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

Bu aşamalar artık masaüstü bilgisayar, dizüstü bilgisayar veya ileri teknoloji telefon gibi üst düzey cihazlarda çok fazla zaman almıyor. Ancak ortalama bir cep telefonunda bu işlem beş ila on kat daha uzun sürebilir. Etkileşimi geciktiren bu durumu azaltmaya çalışmamız önemlidir.

Uygulamanızla ilgili bu sorunları tespit etmenize yardımcı olmak için Lighthouse'a yeni bir JavaScript başlatma süresi denetimi ekledik.

JavaScript başlatma süresi
Şek. 11. JavaScript başlatma süresi denetimi

Oodle uygulamasında ise JavaScript başlatma işleminde 1, 8 saniye harcandığı belirtildi. Tüm rotalarımızı ve bileşenlerimizi tek bir monolitik JavaScript paketine statik olarak aktarıyorduk.

Bu sorunu çözmek için kullanılan tekniklerden biri kod bölmedir.

Kod bölme, pizza gibidir

Kod bölme, kullanıcılarınıza bir pizza değerinde JavaScript vermek yerine, ihtiyaç duydukça tek bir dilim vermeyi ifade eder.

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

Uygulamamıza kod bölme özelliğini ekledik ve statik içe aktarmalardan dinamik içe aktarmalara geçtik. Bu sayede, kodu gerektiğinde eşzamansız olarak tembel yükleyebiliyoruz.

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

Bu değişiklik, paketlerimizin boyutunu küçültmenin yanı sıra JavaScript başlatma süremizi de kısalttı. Bu, süreyi 0,78 saniyeye düşürerek uygulamayı% 56 daha hızlı hale getirdi.

Genel olarak, JavaScript ağırlıklı bir deneyim oluşturuyorsanız kullanıcıya yalnızca ihtiyacı olan kodu 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ık boyutunuzu nasıl küçültebileceğinizle ilgili birkaç fikir edinmek için webpack-libs-optimizations deposuna göz atın.

Resimleri optimize edin

Resim yükleme performansıyla ilgili şaka

Oodle uygulamasında çok fazla resim kullanıyoruz. Maalesef Lighthouse, bu konuda bizim kadar hevesli değildi. Hatta üç resimle ilgili denetlemenin üçünde de başarısız olduk.

Resimlerimizi optimize etmeyi unutmuşuz, boyutlarını doğru ayarlamamışız ve diğer resim biçimlerini kullanarak da biraz kazanç elde edebiliriz.

Resim denetimleri
Şek. 14. Lighthouse görüntü denetimleri

Görsellerimizi optimize ederek başladık.

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

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

Bu sayede, gelecekte eklenen resimlerin otomatik olarak optimize edilmesini sağlayabilirsiniz. Akamai gibi bazı CDN'ler veya Cloudinary, Fastly ya da Uploadcare gibi üçüncü taraf çözümleri, kapsamlı resim optimizasyonu çözümleri sunar. Bu nedenle, resimlerinizi bu hizmetlerde de 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
Şek. 15. Optimizasyondan önce ve sonra

Arka plan PNG'miz, webpack'te büyük olarak işaretlendi ve bu doğruydu. Boyutunu görünüm boyutuna göre doğru şekilde ayarlayıp ImageOptim'den geçirdikten sonra 100 KB'a düştük. Bu boyut kabul edilebilir.

Sitemizdeki birden fazla resim için bu işlemi tekrarladığımızda sayfanın genel ağırlığını önemli ölçüde azaltabildik.

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

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

Oodle uygulamasında, ana sayfada giriş dizisi olarak GIF kullanıyorduk. Lighthouse'a göre, daha verimli bir video biçimine geçerek 7 MB'tan fazla tasarruf edebiliriz. Klip yaklaşık 7,3 MB ağırlığındaydı.Bu, makul bir web sitesi için çok fazla olduğundan, daha geniş tarayıcı desteği için iki kaynak dosyası (MP4 ve WebM) içeren bir video öğesine dönüştürdük.

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

Animasyonlu GIF'imizi MP4 dosyasına dönüştürmek için FFmpeg aracını kullandık. WebM biçimi daha da fazla tasarruf sağlar. ImageOptim API, bu tür bir dönüşümü 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ı kurtarmayı başardık. Bu işlem, boyutun yaklaşık 1 MB'a düşmesini sağladı.

Ancak 1 MB, özellikle bant genişliği sınırlı olan bir kullanıcı için kablo üzerinden gönderilmesi gereken büyük bir kaynaktır. Neyse ki Effective Type API'yi kullanarak bu kullanıcıların yavaş bant genişliğine sahip olduğunu anlayıp onlara çok daha küçük bir JPEG gönderebildik.

Bu arayüz, kullanıcının kullandığı ağ türünü tahmin etmek için etkin gidiş dönüş süresini ve indirme değerlerini kullanır. Yalnızca bir dize (yavaş 2G, 2G, 3G veya 4G) döndürür. Dolayısıyla bu değere bağlı olarak, kullanıcı 4G'nin altında bir bağlantı kullanıyorsa video öğesini resimle değiştirebiliriz.

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

Bu durum deneyimi biraz etkilese de site en azından yavaş bağlantıda kullanılabilir.

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

Dönen öğeler, kaydırma çubukları veya çok uzun sayfalar, kullanıcı bunları sayfada hemen göremese de genellikle resimleri yükler.

Lighthouse, bu davranışı ekran dışı resimler denetiminde işaretler. Ayrıca, Geliştirici Araçları'nın ağ panelinde bu durumu kendiniz de görebilirsiniz. Sayfada yalnızca birkaç resim görünürken çok sayıda resim geliyorsa bu resimleri tembel yüklemeyi düşünebilirsiniz.

Tembel yükleme, tarayıcıda henüz yerel olarak desteklenmediği için bu özelliği eklemek için JavaScript kullanmamız gerekiyor. Oodle kapaklarımıza geç 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 aynı zamanda optimum kullanıcı deneyimi için görünümün yakınındaki öğeleri proaktif olarak önceden getirdiği için akıllı bir kütüphanedir. Ayrıca, çok verimli görünürlük aramaları yapmanızı sağlayan IntersectionObserver isteğe bağlı entegrasyonu da sunar.

Bu değişiklikten sonra resimlerimiz isteğe bağlı olarak getiriliyor. Bu konuyu daha ayrıntılı olarak incelemek isterseniz çok kullanışlı ve kapsamlı bir kaynak olan images.guide adresini ziyaret edin.

Tarayıcının kritik kaynakları erken sunmasına yardımcı olma

Tarayıcıya gönderilen her bayt aynı öneme sahip değildir ve tarayıcı bunu bilir. Birçok tarayıcı, önce hangi verilerin getirilmesi gerektiğine karar vermek için sezgisel yöntemler kullanır. Bu nedenle bazen CSS'yi resimlerden veya komut dosyalarından önce getirirler.

Sayfanın yazarları olarak tarayıcıya bizim için gerçekten önemli olan şeyleri bildirmemiz yararlı olabilir. Neyse ki son birkaç yıldır tarayıcı satıcıları bu konuda bize yardımcı olmak için bir dizi özellik ekliyor. Örneğin, link rel=preconnect, preload veya prefetch gibi kaynak ipuçları.

Web platformuna getirilen bu özellikler, tarayıcının doğru şeyi doğru zamanda getirmesine yardımcı olur ve komut dosyası kullanılarak yapılan bazı özel yükleme, mantığa dayalı yaklaşımlardan biraz daha verimli olabilir.

Lighthouse'un bu özelliklerden bazılarını etkili bir şekilde kullanma konusunda bize nasıl yol gösterdiğine bakalım.

Lighthouse'un yapmamızı istediği ilk şey, herhangi bir kaynağa birden fazla maliyetli gidiş-geliş yapmaktan kaçınmaktır.

Herhangi bir kaynağa birden fazla ve maliyetli gidiş-dönüş yolculuk yapmaktan kaçının.
Şekil 17. Herhangi bir kaynağa birden fazla ve maliyetli gidiş dönüş yolculuğu yapmaktan kaçının.

Oodle uygulamasında Google Yazı Tipleri'ni yoğun bir şekilde kullanıyoruz. Sayfanıza bir Google Font stil sayfası eklediğinizde iki alt alan adına bağlanır. Lighthouse'un bize söylediği ise bu bağlantıyı ısıtabilirsek ilk bağlantı süremizde 300 milisaniyeye kadar tasarruf edebileceğimizdir.

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

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

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

Önemli istekleri önceden yükleme
Şekil 18. Önemli istekleri önceden yükleme

<link rel=preload> çok güçlüdür. Tarayıcıya, mevcut gezinme kapsamında bir kaynağın gerekli olduğunu bildirir ve tarayıcının bu kaynağı mümkün olan en kısa sürede getirmesini sağlamaya çalışır.

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.

Bir web yazı tipinde önceden yükleme şu şekilde görünür: rel=preload belirtirken yazı tipi türüyle birlikte as değerini iletirsiniz ve ardından yüklemeye çalıştığınız yazı tipi türünü (ör. woff2) belirtirsiniz.

Bu durumun sayfanız üzerindeki etkisi oldukça belirgindir.

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

Normalde, bağlantı rel preload kullanılmadığında web yazı tipleri sayfanız için kritikse tarayıcının yapması gereken ilk şey HTML'nizi getirmek, CSS'nizi ayrıştırmak ve çok daha sonra web yazı tiplerinizi getirmektir.

Bağlantı rel preload özelliğini kullandığınızda tarayıcı, HTML'nizi ayrıştırır ayrıştırmaz bu web yazı tiplerini çok daha erken getirmeye başlayabilir. Uygulamamızda bu sayede, web yazı tiplerimizi kullanarak metin oluşturma süresini bir saniye kısaltabildik.

Google Fonts'u kullanarak yazı tiplerini önceden yüklemeyi deneyecekseniz bu işlem biraz daha karmaşık.

Stil sayfalarımızdaki yazı tipi yüzlerimizde belirttiğimiz Google Font 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, bağlantı önceden yükleme gibi özelliklere erişmenizi sağladığı için çok faydalı olabilir.

Bizim durumumuzda, Google Web Fonts Helper aracının bu web yazı tiplerinden bazılarını çevrimdışı hale getirmemize ve yerel olarak ayarlamamıza yardımcı olmada gerçekten yararlı olduğunu gördük. Bu nedenle, bu aracı inceleyin.

Kritik kaynaklarınızın bir parçası olarak web yazı tiplerini kullanıyor olsanız da JavaScript kullanıyor olsanız da tarayıcının kritik kaynaklarınızı mümkün olan en kısa sürede sunmasına yardımcı olmaya çalışın.

Deneysel: Öncelik ipuçları

Bugün sizinle özel bir şey paylaşmak istiyoruz. Kaynak ipuçları ve önceden yükleme gibi özelliklerin yanı sıra, öncelik ipuçları adını verdiğimiz yepyeni bir deneysel tarayıcı özelliği üzerinde çalışıyoruz.

Başlangıçta görünür olan içerik için öncelik ayarlama
Şekil 20. Öncelik ipuçları

Bu yeni özellik, tarayıcıya bir kaynağın ne kadar önemli olduğunu belirtmenize olanak tanır. Bu özellik, düşük, yüksek veya otomatik değerlerine sahip yeni bir özellik (önem) sunar.

Bu sayede, çekişmeyi azaltmak için kritik olmayan stiller, resimler veya Fetch API çağrıları gibi daha az önemli kaynakların önceliğini düşürmeyi iletebiliriz. Ayrıca, ana resimlerimiz gibi daha önemli öğelerin önceliğini de artırabiliriz.

Oodle uygulamamızda bu durum, optimize edebileceğimiz pratik bir alanla sonuçlandı.

Başlangıçta görünür olan içerik için öncelik ayarlama
Şek. 21. Başlangıçta görünür olan içerik için öncelik belirleme

Resimlerimize geç yükleme özelliğini eklemeden önce tarayıcı, tüm doodle'larımızın bulunduğu bu resim döngüsünü kullanıyordu ve döngünün en başında tüm resimleri yüksek öncelikle getiriyordu. Ancak kullanıcının en çok önem verdiği resimler, maalesef karuselin ortasındaki resimlerdi. Bu nedenle, arka plan resimlerinin önemini çok düşük, ön plan resimlerinin önemini ise çok yüksek olarak ayarladık. Bu işlem, yavaş 3G bağlantısında iki saniyelik bir etki yarattı ve bu resimleri ne kadar hızlı getirebildiğimizi ve oluşturabildiğimizi gösterdi. Dolayısıyla olumlu bir deneyim yaşadım.

Bu özelliği birkaç hafta içinde Canary'ye getirmeyi planlıyoruz. Bu nedenle, bu özelliği kullanıma sunmamızı bekleyin.

Web yazı tipi yükleme stratejiniz olsun

Tipografi, iyi tasarımın temelidir. Web yazı tipleri kullanıyorsanız ideal olarak metninizin oluşturulmasını engellemek istemezsiniz ve kesinlikle görünmez metin göstermek istemezsiniz.

Bunu artık Lighthouse'ta web yazı tipleri yüklenirken görünmez metinden kaçının denetimiyle vurguluyoruz.

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

Web yazı tiplerinizi font-face bloğu kullanarak yüklerseniz tarayıcının, web yazı tipinin getirilmesi uzun sürdüğünde ne yapacağına karar vermesine izin vermiş olursunuz. Bazı tarayıcılar, sistem yazı tipine geri dönmeden önce bu işlem için üç saniye kadar bekler ve indirildikten sonra yazı tipini değiştirir.

Bu görünmez metni önlemeye çalışıyoruz. Bu nedenle, web yazı tipi çok uzun sürseydi bu hafta yayınlanan klasik doodle'ları göremezdik. Neyse ki font-display adlı yeni bir özellik sayesinde bu süreç üzerinde çok daha fazla kontrol sahibi olabilirsiniz.

    @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 ne kadar sürede değiştirileceğine bağlı olarak nasıl oluşturulacağına veya yedekleneceğine karar vermenize yardımcı olur.

Bu örnekte, font görüntüleme değiştirme özelliğini kullanıyoruz. Swap, yazı tipi yüzüne sıfır saniyelik bir engelleme süresi ve sonsuz bir değiştirme süresi verir. Bu, tarayıcının, yazı tipi yüklenmesi uzun sürerse yedek yazı tipiyle metninizi hemen çizeceği anlamına gelir. Yazı tipi kullanıma sunulduğunda bu yazı tipiyle değiştirilir.

Uygulamamızda bu özellik, anlamlı metinleri çok erken bir aşamada göstermemize ve hazır olduğunda web yazı tipine geçmemize 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ı tiplerini kullanıyorsanız iyi bir web yazı tipi yükleme stratejiniz olmalıdır.

Yükleme deneyiminizi yazı tipleri için optimize etmek amacıyla kullanabileceğiniz birçok web platformu özelliği vardır. Ayrıca, Zach Leatherman'ın Web Font Recipes deposuna da göz atın. Bu depo gerçekten çok faydalı.

Oluşturmayı engelleyen komut dosyalarını azaltma

Uygulamamızın, indirme zincirinde daha erken göndererek en azından temel kullanıcı deneyimini biraz daha erken sunabileceğimiz başka bölümleri de var.

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

Oluşturmayı engelleyen stil sayfaları fırsatını azaltın
Şek. 24. Oluşturmayı engelleyen stil sayfaları fırsatını azaltın

Harici stil sayfalarının indirilmesi ve işlenmesi, oluşturma sürecimizin ilerlemesini engelliyor.

Bazı stilleri biraz daha erken sunarak kritik oluşturma yolumuzu optimize etmeyi deneyebiliriz.

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

Bizim durumumuzda, derleme adımında kritik içeriğimizi index.html'ye satır içi olarak yerleştirmek için Critical adlı bir NPM modülü kullandık.

Bu modül işin büyük bir kısmını bizim için halletse de farklı rotalarda sorunsuz çalışmasını sağlamak biraz zor oldu.

Dikkatli davranmazsanız veya site yapınız çok karmaşıksa uygulama kabuğu mimarisini en başından planlamadıysanız bu tür bir kalıbı tanıtmak gerçekten zor olabilir.

Bu nedenle, performansla ilgili hususları en başından dikkate almak çok önemlidir. Başlangıçtan itibaren performansa yönelik bir tasarım yapmazsanız daha sonra bu işlemi yaparken sorunlarla karşılaşma olasılığınız yüksektir.

Sonunda riskimiz karşılığını verdi. Uygulamayı çalışır hale getirmeyi başardık ve uygulama, içeriği çok daha erken sunmaya başladı. Böylece ilk anlamlı gösterim süremiz önemli ölçüde iyileşti.

Sonuç

Sitemize uyguladığımız performans optimizasyonlarının uzun bir listesini paylaştık. Sonuca bakalım. Bu, uygulamamızın optimizasyondan önce ve sonra 3G ağında orta seviye bir mobil cihazda nasıl yüklendiğini gösterir.

Lighthouse performans puanı 23'ten 91'e yükseldi. Bu, hız açısından oldukça iyi bir ilerleme. Tüm değişiklikler, Lighthouse raporunu sürekli olarak kontrol etmemiz ve takip etmemiz sayesinde yapıldı. Tüm iyileştirmeleri teknik olarak nasıl uyguladığımızı incelemek isterseniz depomuza, özellikle de orada yer alan PR'lere göz atabilirsiniz.

Tahmine dayalı performans: Veriye dayalı kullanıcı deneyimleri

Makine öğreniminin gelecekte birçok alanda heyecan verici bir fırsat sunduğuna inanıyoruz. Gelecekte daha fazla denemeye yol açacağını umduğumuz bir fikir, gerçek verilerin oluşturduğumuz kullanıcı deneyimlerine gerçekten rehberlik edebileceğidir.

Bugün, kullanıcının isteyebileceği veya ihtiyaç duyabileceği şeyler hakkında çok fazla keyfi karar veriyoruz. Bu nedenle, önceden getirilmeye, önceden yüklenmeye veya önceden önbelleğe alınmaya değer olan şeyler hakkında da keyfi kararlar veriyoruz. Doğru tahmin edersek az miktarda kaynağa öncelik verebiliriz ancak bunu tüm web sitesine ölçeklendirmek gerçekten zordur.

Aslında, optimizasyonlarımızı daha iyi bilgilendirmek için kullanabileceğimiz verilerimiz var. Google Analytics Reporting API'yi kullanarak sitemizdeki herhangi bir URL için sonraki en iyi sayfa ve çıkış yüzdelerine göz atabilir, bu sayede hangi kaynaklara öncelik vermemiz gerektiği konusunda sonuçlar çıkarabiliriz.

Bunu iyi bir olasılık modeliyle birleştirirsek içerikleri agresif bir şekilde önceden getirerek kullanıcı verilerini boşa harcamaktan kaçınırız. Bu Google Analytics verilerinden yararlanabilir ve bu tür modelleri uygulamak için makine öğrenimi ile Markov zincirleri veya sinir ağı gibi 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 mutluluk duyuyoruz.

Guess.js
Şek. 26. Guess.js

Guess.js, web için veriye dayalı kullanıcı deneyimlerine odaklanan bir projedir. Bu kılavuzun, web performansını artırmak için verileri kullanma konusunda size ilham vereceğini ve bu konuda daha da ileri gitmenizi sağlayacağını umuyoruz. Bu çözüm tamamen açık kaynaklıdır ve GitHub'da kullanıma sunulmuştur. Bu özellik, Minko Gechev, Gatsby'den Kyle Matthews, Katie Hempenius ve diğer birçok kişi tarafından açık kaynak topluluğuyla işbirliği içinde geliştirilmiştir.

Guess.js'ye göz atın ve düşüncelerinizi bizimle paylaşın.

Özet

Puanlar ve metrikler, web'in hızını artırmak için faydalı olsa da bunlar yalnızca araçtır, hedefin kendisi değildir.

Hepimiz hareket halindeyken sayfa yükleme hızının yavaş olmasını deneyimledik. Ancak artık kullanıcılarımıza gerçekten hızlı yüklenen daha keyifli deneyimler sunma fırsatımız var.

Performansı artırmak 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.

Şu kişilere özel teşekkür ederiz: Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse ve Google Doodles.