Web Performance

Siteniz neden daha küçük değil, daha az istek göndermeli

Küçük dosyalar ücretsiz değildir. Modern HTTP istek ek yükünü küçülttü, önemsiz hâle getirmedi.

The Wux Webtools Team The Wux Webtools Team 12 dakika okuma Yapay zeka destekli, insan tarafından gözden geçirilmiş
A stylized browser waterfall showing many small requests simplified into fewer intentional requests.
İçindekiler
  1. “Her dosyayı küçült yeter” rahatlatıcı miti
  2. İstekler yalnızca byte değildir
  3. “Ama HTTP/2 bunu çözmüştü,” çoğunlukla hayır
  4. Gerçek waterfall’da yaşar
  5. Daha küçük dosyalar hâlâ önemlidir — sadece eşit ölçüde değil
  6. Çok sayıda küçük dosyanın gizli maliyetleri
  7. 1. Geç keşif
  8. 2. Header ek yükü
  9. 3. Main-thread kesintisi
  10. 4. Cache karmaşıklığı
  11. Bundling geri döndü, ama muhakemeyle
  12. Üçüncü taraf istekler ekstra şüpheyi hak eder
  13. Pratik bir istek azaltma kontrol listesi
  14. Kaldırın
  15. Düşünerek birleştirin
  16. Erteleyin
  17. Doğru cache’leyin
  18. Yeniden ölçün
  19. İyi olan nasıl görünür

“Her dosyayı küçült yeter” rahatlatıcı miti

Yıllar boyunca web performansı tavsiyesi basit duyuldu: her şeyi sıkıştır, her şeyi minify et, her varlığı küçült.

Bu tavsiye hâlâ genel olarak doğru. 40 KB’lık bir script genellikle 400 KB’lık bir script’ten iyidir. Optimize edilmiş bir görsel, ham export’tan iyidir. Brotli, AVIF, CSS minification, tree shaking ve font subsetting önemlidir.

Ancak birçok production sitesinde daha büyük sorun artık tek bir aşırı büyük dosya değildir. Sorun, sayfa kullanılabilir hissettirmeden önce tarayıcının istemek zorunda kaldığı şeylerin sayısıdır.

Bir sayfa dosya boyutları açısından disiplinli görünebilir ve yine de yavaş olabilir; çünkü 120 istek gönderir: CSS parçaları, JavaScript chunk’ları, üçüncü taraf tag’ler, font dosyaları, tracking pixel’leri, icon sprite’ları, JSON endpoint’leri, preload’lar, analytics beacon’ları ve cache revalidation’ları. Her biri “küçük” olabilir. Birlikte uzun ve kırılgan bir waterfall oluştururlar.

Pratik kural şudur: tekil varlıklar makul ölçüde sıkıştırıldıktan sonra, istek sayısını azaltmak çoğu zaman her dosyadan birkaç kilobayt tıraşlamaktan daha fazla kullanıcı deneyimi iyileştirir.

İstekler yalnızca byte değildir

Bir ağ isteği yalnızca veri aktarımı değildir. Bir iş dizisidir.

Tarayıcı kaynağı keşfetmek, ne zaman getireceğine karar vermek, diğer kaynaklara karşı zamanlamak, header’ları göndermek, sunucuyu beklemek, header’ları almak, yanıtı ayrıştırmak, çoğu zaman açmak ve sonra onunla yararlı bir şey yapmak zorundadır.

Bu “yararlı şey” pahalı olabilir. Bir JavaScript dosyasının ayrıştırılması, derlenmesi ve çalıştırılması gerekir. Bir CSS dosyası render’ı engelleyebilir. Bir font dosyası okunabilir metni geciktirebilir veya layout shift’e neden olabilir. Bir görsel Largest Contentful Paint öğesini etkileyebilir. Üçüncü taraf bir script kendi bağımlılık zincirini getirebilir.

Dosyalar küçük olduğunda bile istek sayısının hâlâ önemli olmasının nedeni budur. 3 KB’lık bir script, render’ı engelliyorsa, geç geliyorsa ve ana thread üzerinde yanlış anda çalışıyorsa 30 KB’lık bir görselden daha kötü olabilir.

Bir Lighthouse raporu okuyor ve onlarca ayrı uyarı tarafından cezalandırılmış gibi hissediyorsanız, tek tek skorlardan önce istek waterfall’una bakarak başlayın. Paniklemeden Lighthouse raporu okuma konusunda pratik bir rehberimiz var; ama kısa hâli şudur: ilk render’ı neyin engellediğini ve ana içeriği neyin geciktirdiğini bulun.

“Ama HTTP/2 bunu çözmüştü,” çoğunlukla hayır

HTTP/2 ve HTTP/3 isteklerin ekonomisini değiştirdi. Multiplexing, header compression ve daha iyi bağlantı davranışı getirdiler. Basitçe söylemek gerekirse, tarayıcılar daha az bağlantı üzerinden birden fazla istek göndermede çok daha iyi hâle geldi.

Bu gerçek bir iyileşmeydi. Ayrıca yalnızca bağlantı sınırlarından kaçınmak için yapılan aşırı CSS sprite’ları ve devasa birleştirilmiş bundle’lar gibi bazı eski alışkanlıkları da bitirdi.

Ama HTTP/2 istekleri ücretsiz yapmadı.

Multiplexing, birçok kaynak bir bağlantıyı paylaştığında yardımcı olur; ancak tarayıcının bunları hâlâ önceliklendirmesi gerekir. Sunucuların hâlâ yanıt vermesi gerekir. İstemcinin hâlâ her yanıtı işlemesi gerekir. Congestion, packet loss, TLS negotiation, DNS lookup, cache miss’leri ve main-thread baskısı hâlâ vardır.

HTTP/3 özellikle connection migration ve transport katmanındaki head-of-line blocking çevresinde bazı transport davranışlarını iyileştirir. Kaynakları keşfetme, zamanlama, indirme, ayrıştırma ve çalıştırma maliyetini ortadan kaldırmaz.

Bu yüzden modern hedef “her şeyi tek bir dev dosyada bundle etmek” değildir. Hedef “daha az kritik istek göndermek ve kalan istekleri bilinçli hâle getirmek”tir.

Gerçek waterfall’da yaşar

Performans sorunları kendilerini nadiren tek bir metrikte duyurur. Şekil olarak görünürler.

Bir tarayıcı network panelini açın ve ilk birkaç saniyeye bakın. Şunları sorun:

  • Ana içerik görünmeden önce kaç istek başlıyor?
  • Hangi istekler render’ı engelliyor?
  • Önemli kaynaklar geç mi keşfediliyor?
  • Üçüncü taraf script’ler birinci taraf CSS, font veya görsellerle rekabet ediyor mu?
  • Birçok dosya doğrudan cache’ten sunulmak yerine 304 yanıtı mı döndürüyor?
  • İkonlar, fontlar veya UI parçaları sayfanın ihtiyaç duyduğundan daha fazla dosyaya mı bölünmüş?

Hızlı bir sayfanın erken waterfall’u genellikle sıkıcıdır. Az sayıda kritik kaynak erken gelir. Kritik olmayan kaynaklar bekler. Üçüncü taraf script’ler geciktirilir, sınırlandırılır veya kaldırılır. Tarayıcı sayfayı boyayabilmeden önce yirmi önceliği idare etmeye zorlanmaz.

Yavaş bir sayfanın waterfall’u çoğu zaman gergindir: çok sayıda küçük dosya, çok sayıda origin ve çok sayıda geç keşif.

Daha küçük dosyalar hâlâ önemlidir — sadece eşit ölçüde değil

Bu, sıkıştırmaya veya optimizasyona karşı bir argüman değildir. Byte’ları optimize ederken koordinasyonu görmezden gelmeye karşı bir argümandır.

Daha küçük dosyalar en çok kaynak büyük, render-blocking veya ana içerik yolunun parçası olduğunda önemlidir. Örneğin:

  • Hero görseli doğru boyutlandırılmalı ve encode edilmelidir.
  • Render-blocking CSS yalın olmalıdır.
  • İlk etkileşim için gereken JavaScript minimumda olmalıdır.
  • Fontlar subset edilmeli, sıkıştırılmalı ve gerçekten kullanılan weight’lerle sınırlanmalıdır.

Fontlar yaygın bir örnektir. Ekipler çoğu zaman bir font dosyasının 24 KB mı 31 KB mı olduğuna takılırken altı weight, iki style ve birden fazla family gönderir. Daha iyi çözüm bir dosyadan 7 KB tıraşlamak değildir. Daha az font dosyası göndermektir. Tipografi performans çalışmanızın bir parçasıysa, web fontları çoğu sitede hâlâ en kolay kazanımlardan biridir.

Görseller de aynı deseni izler. AVIF veya WebP anlamlı byte tasarrufu sağlayabilir; ancak fold üstünde on dekoratif görsel göndermek hâlâ kötü bir plandır. Daha iyi formatlar seçin, evet; ama her görselin gerçekten istenmesi gerekip gerekmediğini de sorgulayın. Format kararları için AVIF ne zaman WebP’yi geçer, ne zaman geçmez rehberimiz bu istek sayısı çalışmasına yararlı bir eşlikçidir.

Çok sayıda küçük dosyanın gizli maliyetleri

Çok sayıda küçük istek, yalnızca toplam aktarılan byte’a bakarsanız görünmeyen sorunlar yaratma eğilimindedir.

1. Geç keşif

Tarayıcılar keşfetmedikleri şeyi isteyemez. Bir CSS dosyası bir font’a referans verebilir. Bir script başka bir script’i import edebilir. Bir component hydration’dan sonra JSON isteyebilir. Her bağımlılık zincirde bir adım daha yaratır.

Zincir ne kadar derinse, önemli iş o kadar geç başlar.

2. Header ek yükü

Her istek ve yanıt header içerir. Header compression özellikle HTTP/2 ve HTTP/3 üzerinde yardımcı olur, ancak ek yükü ortadan kaldırmaz. Cookie’ler bunu çok daha kötü hâle getirebilir. Siteniz her istekle büyük cookie’ler gönderiyorsa, küçük varlıklar pratikte daha az küçük olur.

Statik varlıkların çoğu zaman cookie’siz path veya domain’lerde yaşaması gerektiğinin ve cache header’larının ilgiyi hak ettiğinin nedenlerinden biri budur. Header’lar production’da tuhaf davranıyorsa, redirect ve HTTP header’larını debug etmek genellikle tahmin etmekten daha hızlıdır.

3. Main-thread kesintisi

Çok sayıda JavaScript chunk’ı tekrarlanan ayrıştırma ve çalıştırma işi yaratabilir. Her chunk küçük olsa bile tarayıcı kodu değerlendirmek için sürekli durabilir. Bu, Interaction to Next Paint’e zarar verebilir ve sayfanın titrek hissettirmesine neden olabilir.

Kullanıcı her dosyanın küçük olmasıyla ilgilenmez. Bir menüye dokunmanın 600 milisaniye sürmesiyle ilgilenir.

4. Cache karmaşıklığı

Varlıkları bölmek dikkatli yapıldığında caching’i iyileştirebilir. Stabil bir vendor bundle ve değişen bir app bundle iyi bir ayrım olabilir.

Ancak aşırı chunking geri tepebilir. Daha fazla dosya, daha fazla cache lookup, daha fazla revalidation fırsatı, daha fazla version koordinasyonu ve değişmesi gerekmeyen kaynakları yanlışlıkla invalidate etmenin daha fazla yolu demektir.

Bundling geri döndü, ama muhakemeyle

Web performansının ilk dönemi bundling’i severdi çünkü tarayıcıların katı bağlantı sınırları vardı. Sonra HTTP/2 geldi ve birçok ekip agresif code splitting’e sert biçimde yöneldi. Bunun bir kısmı yararlıydı. Bir kısmı batıl inanca dönüştü.

Mantıklı orta yol route-aware bundling’dir.

Tipik bir marketing sitesi veya content sitesi için:

  • İlk render için gereken CSS’i inline edin veya yalnızca onu yükleyin.
  • Global JavaScript’i küçük tutun.
  • Küçük modülleri ayrı network isteklerine bölmekten kaçının.
  • Hemen gerekmeyen etkileşimli özellikleri geciktirin.
  • Maliyetini haklı çıkarmayan üçüncü taraf script’leri kaldırın.

Bir application için:

  • Her component’e göre değil, route veya büyük feature’a göre bölün.
  • Paylaşılan bağımlılıkları stabil ve cache’lenebilir tutun.
  • Yalnızca yakında kesinlikle gerekecek kaynakları preload edin.
  • Public sayfalarda admin, dashboard, editor veya experiment kodu yüklemekten kaçının.
  • Yalnızca bundle boyutunu değil, etkileşim maliyetini ölçün.

Bundling otomatik olarak iyi değildir. Code splitting otomatik olarak iyi değildir. Yararlı soru şudur: Bu bölme, tarayıcının bir sonraki anlamlı kullanıcı deneyimini daha erken sunmasına yardımcı oluyor mu?

Üçüncü taraf istekler ekstra şüpheyi hak eder

Birinci taraf istekler en azından sizin kontrolünüzdedir. Üçüncü taraf istekler ise çoğu zaman göründüklerinden daha yavaş, daha az öngörülebilir ve daha pahalıdır.

Tek bir tag manager analytics, ads, heatmap’ler, chat widget’ları, A/B testing, consent araçları ve personalization script’lerini tetikleyebilir. Her vendor daha fazla istek getirebilir. Bazıları erken çalışır. Bazıları main thread’i engeller. Bazıları release süreciniz olmadan değişir.

En iyi üçüncü taraf optimizasyonu silmektir. İkinci en iyisi geciktirmektir.

Üçüncü taraf bir script eklemeden önce şunları sorun:

  • Kullanıcı sayfayı görmeden önce bunun yüklenmesi gerekiyor mu?
  • Her sayfada yüklenmesi gerekiyor mu?
  • Consent, etkileşim veya idle time sonrasında yüklenebilir mi?
  • İçeride bunun sahibi kim?
  • Performans maliyetine değdiğini hangi metrik kanıtlıyor?

Performansın governance’a dönüştüğü yer burasıdır. Birinin hayır diyebilmesine izin verilmelidir.

Pratik bir istek azaltma kontrol listesi

En önemli sayfalardan başlayın: homepage, pricing page, product page, checkout, signup veya en iyi landing page’ler. Sonra waterfall üzerinde ilerleyin.

Kaldırın

  • Kullanılmayan JavaScript ve CSS’i silin.
  • Eski experiment’leri, terk edilmiş pixel’leri ve duplicate analytics’i kaldırın.
  • Kullanılmayan font weight’lerini ve icon library’lerini çıkarın.
  • Uygun olduğunda dekoratif görselleri CSS ile değiştirin.

Düşünerek birleştirin

  • Her zaman birlikte yüklenen küçük JavaScript modüllerini bundle edin.
  • Aynı render path’i engelleyen küçük CSS dosyalarını birleştirin.
  • Bakım yapılabilirliğe zarar vermeden istekleri azaltıyorsa tekrar eden ikonlar için SVG sprite’ları veya inline SVG kullanın.

Erteleyin

  • Fold altındaki görselleri lazy-load edin.
  • Kritik olmayan script’leri first paint veya kullanıcı etkileşiminden sonraya geciktirin.
  • Yorumları, embed’leri, haritaları, chat’i ve video player’ları yalnızca gerektiğinde yükleyin.

Doğru cache’leyin

  • Version’lanmış statik varlıklar için uzun ömürlü caching kullanın.
  • Nadiren değişen dosyalar için gereksiz revalidation’dan kaçının.
  • HTML’i güncel tutun, ama hashed varlıkların cache’te kalmasına izin verin.

Yeniden ölçün

Her değişiklikten sonra waterfall’u tekrar kontrol edin. Hedef mükemmel bir skor değildir. Hedef daha az kritik istek, daha erken yararlı render ve daha az main-thread kesintisidir.

İyi olan nasıl görünür

Sağlıklı bir sayfanın mümkün olan en az isteğe sahip olması gerekmez. Küçük ve bilinçli bir critical path’e sahiptir.

Tarayıcı HTML’i, temel CSS’i, varsa ana içerik görselini, belki navigation veya above-the-fold etkileşim için gereken küçük bir script’i ve metni okunabilir yapmak için gereken minimum font setini alır. Diğer her şey sırasını bekler.

Yalnızca optimize edilmiş bir sayfa ile hızlı hissettiren bir sayfa arasındaki fark budur.

Dosyaları küçültmek hâlâ değerlidir. Ama site zaten makul ölçüde sıkıştırılmışsa, bir sonraki performans kazanımı genellikle bir bundle’dan bir 2 KB daha tasarruf etmek değildir. Bir eksik blocking request, bir eksik font dosyası, bir eksik üçüncü taraf script, bir eksik bağımlılık zinciridir.

Daha az istek tarayıcının işini basitleştirir. Basit olan, kabul etmek istediğimizden daha sık hızlıdır.

Sıkça sorulan sorular

Tek büyük bir bundle, çok sayıda küçük dosyadan daha mı iyidir?
Otomatik olarak değil. Tek dev bir bundle özellikle ilk yüklemede her şeyi geciktirebilir. Çok sayıda küçük dosya ise zamanlama ve çalıştırma ek yükü yaratabilir. Daha iyi desen, her zaman birlikte gereken kaynakları bundle etmek ve route veya büyük feature’a göre bölmektir.
HTTP/2 istek sayısının artık önemli olmadığı anlamına mı gelir?
Hayır. HTTP/2 multiplexing ve header compression yoluyla bazı bağlantı ek yüklerini azaltır, ancak her isteğin hâlâ keşif, önceliklendirme, sunucu, cache, ayrıştırma ve çalıştırma maliyetleri vardır.
Tüm kritik CSS’i inline etmeli miyim?
Gerçekten kritik olan küçük miktarda CSS’i inline etmek first render’a yardımcı olabilir; ancak çok fazla inline etmek HTML’i ağırlaştırır ve cache’lemeyi zorlaştırır. Minimumda tutun ve etkisini ölçün.
İstekleri azaltmak için en kolay yer neresidir?
Fontlar ve üçüncü taraf script’ler çoğu zaman en hızlı kazanımlardır. Birçok site kullanılmayan font weight’leri, duplicate analytics, eski pixel’ler, chat widget’ları veya hemen yüklenmesi gerekmeyen embed’ler gönderir.
Bir sayfada kaç istek olmalı?
Evrensel bir hedef yoktur. Küçük bir içerik sayfasının çok az kritik isteği olmalıdır. Karmaşık bir app daha fazlasına ihtiyaç duyabilir. First render’dan ve ana etkileşim yolundan önceki istekleri azaltmaya odaklanın.

Kaynaklar ve ileri okuma

  1. MDN Web Docs: HTTP caching
  2. web.dev: Optimize Largest Contentful Paint
  3. RFC 9113: HTTP/2
  4. HTTP Archive Web Almanac: Page Weight
Yazar hakkında
The Wux Webtools Team

Son güncelleme:

Devamını oku