Merhaba arkadaşlar, bugün sizlere bir projede performans optimizasyonu yaparken başımı çok ağrıtan ve sonunda "neden daha önce düzgün yapmadım" dediğim bir konudan bahsedeceğim: Tarayıcı önbelleği. Bir kullanıcı sitemizi ikinci kez ziyaret ettiğinde, her şeyin yeniden yüklenmesini izlemek beni deli ediyordu. İşte bu sorunu nasıl kökten çözdüğümü anlatacağım.
Sorunun Tespiti ve Can Sıkıcı Etkisi
Projemde Lighthouse skorlarıma baktığımda, "Serve static assets with an efficient cache policy" uyarısı sürekli karşıma çıkıyordu. Kullanıcılar, her sayfa yenilemede aynı logo, aynı CSS dosyası, aynı ikon fontlarını tekrar tekrar indiriyordu. Bu, hem sunucu band genişliğini gereksiz yere tüketiyor hem de kullanıcı deneyimini yavaşlatıyordu. Özellikle mobil ağlarda bu durum daha da vahimdi. "Bu dosyalar değişmediği sürece neden her seferinde yüklensin ki?" diye düşünmeye başladım.
Çözüm: .htaccess ile Cache-Control Headers'ı Yapılandırmak
Benim projem bir Apache sunucusunda çalıştığı için, çözüm yolum .htaccess dosyasından geçiyordu. Temel mantık, sunucunun tarayıcıya "Bu dosyayı şu kadar süre sakla" talimatını göndermesiydi. Bunun için Cache-Control ve Expires header'larını kullandım.
İşte benim statik asset'lerim için uyguladığım, işe yarayan konfigürasyon:
Bu yapılandırma ile:
Resimler ve fontlar tarayıcıda 1 yıl boyunca saklanıyor (immutable ile, dosya değişmediği sürece sunucuya hiç sorgu bile gitmiyor).
CSS ve JS dosyalarım 1 hafta önbellekte kalıyor.
HTML sayfaları ise hiç önbelleğe alınmıyor, böylece en güncel içerik her zaman gösteriliyor.
Cache Busting: Dosya Değişince Önbelleği Kırma Taktiği
Peki ya CSS dosyama bir güncelleme yaparsam? Kullanıcı eski, önbelleğe alınmış dosyayı kullanmaya devam eder! Bu büyük bir problem. Bunun çözümü ise cache busting. Ben bunu dosya isimlerine version hash'i ekleyerek çözüyorum. Örneğin, style.css yerine style.a1b2c3d4.css gibi bir isim kullanıyorum. Dosya içeriği değiştiğinde, build işlemi sırasında bu hash değişiyor ve tarayıcı bunu yepyeni bir dosya olarak görüp tekrar indiriyor.
Build aracı olarak Webpack veya Vite kullanıyorsanız, bu işlemi otomatik olarak yapılandırabilirsiniz.
Sonuçlar ve Performans Artışı
Bu ayarları yaptıktan sonraki ilk Lighthouse testinde, performans skorumun gözle görülür şekilde arttığını gördüm. Tekrar ziyaretlerde (repeat visit) sayfa yüklenme süresi inanılmaz derecede hızlandı. Sunucuya giden istek sayısı büyük oranda düştü ve CDN maliyetlerimde bile olumlu bir etkisi oldu. Kullanıcılar artık sadece değişen içeriği yüklüyor, sabit asset'ler için beklemek zorunda kalmıyor.
Siz projelerinizde tarayıcı önbelleğini nasıl yönetiyorsunuz? Cache busting için farklı bir yöntem (query string vs.) kullanan var mı? Ya da Nginx kullanıyorsanız, benzer konfigürasyonu nasıl yapıyorsunuz? Yorumlarda deneyimlerinizi paylaşın, tartışalım!
Projemde Lighthouse skorlarıma baktığımda, "Serve static assets with an efficient cache policy" uyarısı sürekli karşıma çıkıyordu. Kullanıcılar, her sayfa yenilemede aynı logo, aynı CSS dosyası, aynı ikon fontlarını tekrar tekrar indiriyordu. Bu, hem sunucu band genişliğini gereksiz yere tüketiyor hem de kullanıcı deneyimini yavaşlatıyordu. Özellikle mobil ağlarda bu durum daha da vahimdi. "Bu dosyalar değişmediği sürece neden her seferinde yüklensin ki?" diye düşünmeye başladım.
Benim projem bir Apache sunucusunda çalıştığı için, çözüm yolum .htaccess dosyasından geçiyordu. Temel mantık, sunucunun tarayıcıya "Bu dosyayı şu kadar süre sakla" talimatını göndermesiydi. Bunun için Cache-Control ve Expires header'larını kullandım.
İşte benim statik asset'lerim için uyguladığım, işe yarayan konfigürasyon:
Kod:
# Görseller, ikonlar, fontlar - Uzun süreli önbellek (1 Yıl)
<FilesMatch "\.(jpg|jpeg|png|gif|ico|svg|webp|woff2|woff|ttf|eot)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# CSS ve JavaScript dosyaları - Orta süreli önbellek (1 Hafta)
<FilesMatch "\.(css|js)$">
Header set Cache-Control "public, max-age=604800"
</FilesMatch>
# HTML dosyaları - Önbelleğe alma YOK (Dinamik içerik)
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</FilesMatch>
Bu yapılandırma ile:
Resimler ve fontlar tarayıcıda 1 yıl boyunca saklanıyor (immutable ile, dosya değişmediği sürece sunucuya hiç sorgu bile gitmiyor).
CSS ve JS dosyalarım 1 hafta önbellekte kalıyor.
HTML sayfaları ise hiç önbelleğe alınmıyor, böylece en güncel içerik her zaman gösteriliyor.
Peki ya CSS dosyama bir güncelleme yaparsam? Kullanıcı eski, önbelleğe alınmış dosyayı kullanmaya devam eder! Bu büyük bir problem. Bunun çözümü ise cache busting. Ben bunu dosya isimlerine version hash'i ekleyerek çözüyorum. Örneğin, style.css yerine style.a1b2c3d4.css gibi bir isim kullanıyorum. Dosya içeriği değiştiğinde, build işlemi sırasında bu hash değişiyor ve tarayıcı bunu yepyeni bir dosya olarak görüp tekrar indiriyor.
Build aracı olarak Webpack veya Vite kullanıyorsanız, bu işlemi otomatik olarak yapılandırabilirsiniz.
Bu ayarları yaptıktan sonraki ilk Lighthouse testinde, performans skorumun gözle görülür şekilde arttığını gördüm. Tekrar ziyaretlerde (repeat visit) sayfa yüklenme süresi inanılmaz derecede hızlandı. Sunucuya giden istek sayısı büyük oranda düştü ve CDN maliyetlerimde bile olumlu bir etkisi oldu. Kullanıcılar artık sadece değişen içeriği yüklüyor, sabit asset'ler için beklemek zorunda kalmıyor.
Siz projelerinizde tarayıcı önbelleğini nasıl yönetiyorsunuz? Cache busting için farklı bir yöntem (query string vs.) kullanan var mı? Ya da Nginx kullanıyorsanız, benzer konfigürasyonu nasıl yapıyorsunuz? Yorumlarda deneyimlerinizi paylaşın, tartışalım!