JavaScript başlangıç optimizasyonu

JavaScript'e daha fazla dayalı siteler oluştururken bazen gönderdiğimiz verilerin bedelini her zaman kolayca göremeyeceğimiz şekillerde öderiz. Bu makalede, sitenizin mobil cihazlarda hızlı bir şekilde yüklenmesini ve etkileşimli olmasını istiyorsanız biraz disiplinin neden yardımcı olabileceğini ele alacağız. Daha az JavaScript yayınlamak, ağ aktarımında daha az zaman harcanması, kodun sıkıştırmasını açmak için daha az zaman harcanması ve bu JavaScript'i ayrıştırmak ve derlemek için daha az zaman harcanması anlamına gelebilir.

Ağ

Çoğu geliştirici, JavaScript'in maliyetini indirme ve yürütme maliyeti açısından değerlendirir. Kullanıcının bağlantısı ne kadar yavaşsa ağ üzerinden daha fazla bayt JavaScript göndermek o kadar uzun sürer.

Tarayıcı bir kaynak istediğinde bu kaynağın getirilmesi ve ardından sıkıştırılmış halinin açılması gerekir. JavaScript gibi kaynakların yürütülmeden önce ayrıştırılması ve derlenmesi gerekir.

Kullanıcının sahip olduğu etkin ağ bağlantısı türü aslında 3G, 4G veya kablosuz bağlantı olmayabileceğinden bu durum sorun teşkil edebilir. Bir kafenin kablosuz ağına bağlı olabilirsiniz ancak 2G hızında bir hücresel hotspot'a bağlı olabilirsiniz.

JavaScript'in ağ aktarım maliyetini şu yöntemlerle azaltabilirsiniz:

  • Yalnızca kullanıcının ihtiyaç duyduğu kodu gönderme.
    • JavaScript'inizi kritik olan ve olmayan bölümlere ayırmak için kod bölme işlemini kullanın. webpack gibi modül paketleyiciler, kod bölmeyi destekler.
    • Kritik olmayan kodları geç yükleme.
  • Sadeleştirme
  • Sıkıştırma
    • Metne dayalı kaynakları sıkıştırmak için en azından gzip kullanın.
    • Brotli kullanmayı düşünün ~q11. Brotli, sıkıştırma oranı açısından gzip'ten daha iyi performans gösterir. CertSimple'ın sıkıştırılmış JS baytlarının boyutunda %17, LinkedIn'in ise yükleme sürelerinde %4 tasarruf etmesine yardımcı oldu.
  • Kullanılmayan kodları kaldırma.
  • Ağ gezilerini en aza indirmek için kodu önbelleğe alma
    • Tarayıcıların yanıtları etkili bir şekilde önbelleğe almasını sağlamak için HTTP önbelleğe alma özelliğini kullanın. Değişmeyen baytların aktarılmasını önlemek için komut dosyaları için en uygun kullanım ömürlerini (max-age) belirleyin ve doğrulama jetonları (ETag) sağlayın.
    • Servis çalışanı önbelleğe alma, uygulama ağınızı dayanıklı hale getirebilir ve V8'in kod önbelleği gibi özelliklere hızlı erişim sağlar.
    • Değişmeyen kaynakları yeniden getirmek zorunda kalmamak için uzun süreli önbelleğe almayı kullanın. Webpack kullanıyorsanız dosya adı karma oluşturma bölümüne bakın.

Ayrıştırma/derleme

İndirildikten sonra JavaScript'in en ağır maliyetlerinden biri, JS motorunun bu kodu ayrıştırması/derlemesi için gereken süredir. Chrome Geliştirici Araçları'nda ayrıştırma ve derleme, Performans panelindeki sarı renkli "Komut dosyası oluşturma" süresinin bir parçasıdır.

ALT_TEXT_HERE

Aşağıdan Yukarıya ve Çağrı Ağacı sekmeleri, tam ayrıştırma/derleme sürelerini gösterir:

ALT_TEXT_HERE
Chrome Geliştirici Araçları Performans paneli > Aşağıdan Yukarıya. V8'in Çalışma Zamanı Çağrı İstatistikleri etkinleştirildiğinde, Ayrıştırma ve Derleme gibi aşamalarda harcanan süreyi görebiliriz.

Peki, bu neden önemli?

ALT_TEXT_HERE

Kod ayrıştırma/derleme işleminin uzun sürmesi, kullanıcının sitenizle etkileşime geçebilme süresini önemli ölçüde geciktirebilir. Ne kadar çok JavaScript gönderirseniz siteniz etkileşimli hale gelmeden önce ayrıştırılması ve derlenmesi o kadar uzun sürer.

Bayt bazında, JavaScript'in tarayıcı tarafından işlenmesi, eşdeğer boyuttaki resim veya web yazı tipine göre daha maliyetlidir - Tom Dale

JavaScript ile karşılaştırıldığında, eşdeğer boyuttaki resimlerin işlenmesiyle ilgili çok sayıda maliyet vardır (bunların yine de kodu çözülmelidir). Ancak ortalama mobil donanımda JS'nin bir sayfanın etkileşimini olumsuz etkileme olasılığı daha yüksektir.

ALT_TEXT_HERE
JavaScript ve resim baytlarının maliyetleri çok farklıdır. Resimler genellikle ana iş parçacığını engellemez veya arayüzlerin kodu çözülüp rasterleştirilirken etkileşimli hale gelmesini engellemez. Ancak JS, ayrıştırma, derleme ve yürütme maliyetleri nedeniyle etkileşimi geciktirebilir.

Ayrıştırma ve derlemenin yavaş olduğunu söylerken bağlam önemlidir. Burada ortalama cep telefonlarından bahsediyoruz. Ortalama kullanıcıların telefonlarında CPU ve GPU'lar yavaş olabilir, L2/L3 önbelleği bulunmayabilir ve hatta bellek kısıtlaması olabilir.

Ağ özellikleri ve cihaz özellikleri her zaman eşleşmez. Mükemmel bir fiber bağlantıya sahip bir kullanıcının cihazına gönderilen JavaScript'i ayrıştırıp değerlendirmek için en iyi CPU'ya sahip olması gerekmez. Bunun tersi de geçerlidir. Ağ bağlantısı çok kötü ama CPU çok hızlı olabilir. — Kristofer Baxter, LinkedIn

Aşağıda, düşük ve yüksek kaliteli donanımlarda yaklaşık 1 MB sıkıştırılmamış (basit) JavaScript'i ayrıştırmanın maliyetini görebiliriz. Piyasadaki en hızlı telefonlar ile ortalama telefonlar arasında kodu ayrıştırma/derleme süresi açısından 2-5 kat fark vardır.

ALT_TEXT_HERE
Bu grafikte, farklı sınıflardaki masaüstü ve mobil cihazlarda 1 MB'lık bir JavaScript paketinin (~250 KB gzip'li) ayrıştırma süreleri vurgulanmaktadır. Ayrıştırma maliyetine bakarken, sıkıştırılmamış rakamları dikkate almak gerekir.Örneğin, gzip ile sıkıştırılmış ~250 KB JS, ~1 MB koda açılır.

CNN.com gibi gerçek bir siteye ne dersiniz?

Üst düzey iPhone 8'de CNN'in JS'sini ayrıştırmak/derlemek yalnızca yaklaşık 4 saniye sürerken ortalama bir telefonda (Moto G4) bu süre yaklaşık 13 saniyedir. Bu durum, kullanıcının bu siteyle tam olarak etkileşime geçme hızını önemli ölçüde etkileyebilir.

ALT_TEXT_HERE
Yukarıda, Apple'ın A11 Bionic çipinin performansını daha ortalama Android donanımına sahip Snapdragon 617 ile karşılaştıran ayrıştırma sürelerini görüyoruz.

Bu durum, yalnızca cebinizdeki telefon yerine ortalama donanımlarda (Moto G4 gibi) test yapmanın önemini vurgular. Ancak bağlam önemlidir: Kullanıcılarınızın cihaz ve ağ koşullarına göre optimizasyon yapın.

ALT_TEXT_HERE
Google Analytics, gerçek kullanıcılarınızın sitenize erişmek için kullandığı mobil cihaz sınıfları hakkında bilgi sağlayabilir. Bu sayede, kullanıcıların karşılaştığı gerçek CPU/GPU kısıtlamalarını anlama fırsatı elde edebilirsiniz.

Gerçekten çok fazla JavaScript mi gönderiyoruz? Err, possibly :)

Mobil cihazlarda JavaScript'in durumunu analiz etmek için HTTP Arşivi'ni (en popüler yaklaşık 500 bin site) kullandığımızda, sitelerin %50'sinin etkileşimli hale gelmesinin 14 saniyeden uzun sürdüğünü görüyoruz. Bu siteler yalnızca JS'yi ayrıştırmak ve derlemek için 4 saniyeye kadar zaman harcar.

ALT_TEXT_HERE

JS ve diğer kaynakları getirip işlemek için gereken süreyi de hesaba kattığınızda, kullanıcıların sayfaların kullanıma hazır olduğunu hissetmeden önce bir süre beklemek zorunda kalması şaşırtıcı olmayabilir. Bu konuda kesinlikle daha iyisini yapabiliriz.

Kritik olmayan JavaScript'leri sayfalarınızdan kaldırmak, aktarım sürelerini, CPU yoğun ayrıştırma ve derleme işlemlerini ve olası bellek ek yükünü azaltabilir. Bu, sayfalarınızın daha hızlı etkileşimli hale gelmesine de yardımcı olur.

Yürütme süresi

Maliyeti olan tek şey ayrıştırma ve derleme değildir. JavaScript yürütme (ayrıştırıldıktan/derlendikten sonra kodun çalıştırılması), ana iş parçacığında gerçekleşmesi gereken işlemlerden biridir. Uzun yürütme süreleri, kullanıcının sitenizle etkileşime geçebileceği süreyi de uzatabilir.

ALT_TEXT_HERE

Komut dosyasının yürütülmesi 50 ms'den uzun sürerse etkileşime hazır olma süresi, JS'nin indirilmesi, derlenmesi ve yürütülmesi için gereken sürenin tamamı kadar gecikir. Alex Russell

Bu sorunu çözmek için JavaScript, ana iş parçacığının kilitlenmesini önlemek amacıyla küçük parçalar halinde olmaktan yararlanır. Yürütme sırasında yapılan iş miktarını azaltıp azaltamayacağınızı araştırın.

Diğer maliyetler

JavaScript, sayfa performansını başka şekillerde de etkileyebilir:

  • Bellek. Sayfalar, GC (çöp toplama) nedeniyle sık sık takılabilir veya duraklayabilir. Bir tarayıcı bellek geri aldığında JS yürütme duraklatılır. Bu nedenle, sık sık çöp toplayan bir tarayıcı, yürütmeyi istediğimizden daha sık duraklatabilir. Sayfaların takılmasını önlemek için bellek sızıntılarından ve sık sık yapılan gc duraklatmalarından kaçının.
  • Çalışma zamanında, uzun süre çalışan JavaScript, ana iş parçacığını engelleyerek sayfaların yanıt vermemesine neden olabilir. İşi daha küçük parçalara bölmek (planlama için requestAnimationFrame() veya requestIdleCallback() kullanarak) duyarlılık sorunlarını en aza indirebilir ve Interaction to Next Paint (INP) metriğini iyileştirebilir.

JavaScript yayınlama maliyetini azaltma kalıpları

JavaScript için ayrıştırma/derleme ve ağ aktarım sürelerini düşük tutmaya çalışırken rotaya dayalı parçalama veya PRPL gibi yardımcı olabilecek kalıplar vardır.

PRPL

PRPL (Push, Render, Pre-cache, Lazy-load), agresif kod bölme ve önbelleğe alma yoluyla etkileşimi optimize eden bir kalıptır:

ALT_TEXT_HERE

Bu özelliğin etkisini görselleştirelim.

V8'in Çalışma Zamanı Çağrı İstatistikleri'ni kullanarak popüler mobil sitelerin ve Progresif Web Uygulamalarının yükleme süresini analiz ediyoruz. Gördüğünüz gibi, ayrıştırma süresi (turuncu renkle gösterilir) bu sitelerin çoğunun zaman harcadığı önemli bir bölümdür:

ALT_TEXT_HERE

PRPL kullanan bir site olan Wego, rotaları için düşük bir ayrıştırma süresi sağlayarak çok hızlı bir şekilde etkileşimli hale geliyor. Yukarıdaki diğer sitelerin çoğu, JS maliyetlerini düşürmek için kod bölme ve performans bütçelerini benimsedi.

Aşamalı önyükleme

Birçok site, etkileşim pahasına içerik görünürlüğünü optimize eder. Büyük JavaScript paketleriniz olduğunda hızlı bir ilk boyama elde etmek için geliştiriciler bazen sunucu tarafı oluşturma kullanır, ardından JavaScript nihayet getirildiğinde etkinlik işleyicileri eklemek için bunu "yükseltir".

Dikkatli olun. Bu yöntemin de kendi maliyetleri vardır. 1) Genellikle etkileşimimizi zorlayabilecek daha büyük bir HTML yanıtı gönderirsiniz, 2) kullanıcıyı, JavaScript işlemi tamamlanana kadar deneyimin yarısının etkileşimli olamayacağı tekinsiz bir vadide bırakabilirsiniz.

Aşamalı önyükleme daha iyi bir yaklaşım olabilir. Minimum düzeyde işlevsel bir sayfa (yalnızca mevcut rota için gereken HTML/JS/CSS'den oluşur) gönderin. Daha fazla kaynak geldikçe uygulama, daha fazla özelliğin geç yüklenmesini ve kilidini açabilir.

ALT_TEXT_HERE
Paul Lewis'ten Kademeli Önyükleme

Görünümde olanla orantılı olarak kod yüklemek en ideal yöntemdir. PRPL ve Kademeli Önyükleme, bunu başarmanıza yardımcı olabilecek kalıplardır.

Sonuçlar

İletim boyutu, düşük kaliteli ağlar için çok önemlidir. Ayrıştırma süresi, CPU'ya bağlı cihazlar için önemlidir. Bu değerlerin düşük olması önemlidir.

Ekipler, JavaScript aktarım ve ayrıştırma/derleme sürelerini düşük tutmak için katı performans bütçeleri uygulayarak başarıya ulaştı. Alex Russell'ın "Can You Afford It?: Real-world Web Performance Budgets" başlıklı makaleyi inceleyin.

ALT_TEXT_HERE
Mimari kararlarımızın uygulama mantığı için ne kadar JS "boşluğu" bırakabileceğini düşünmek faydalı olacaktır.

Mobil cihazları hedefleyen bir site oluşturuyorsanız temsili donanım üzerinde geliştirme yapmaya, JavaScript ayrıştırma/derleme sürelerinizi düşük tutmaya ve ekibinizin JavaScript maliyetlerini takip edebilmesi için bir performans bütçesi benimsemeye özen gösterin.

Daha fazla bilgi