Service Worker ve Cache
Service Worker Performansı Artırır mı?
Service worker ekleyin denir, eklersiniz. Lighthouse skoru bazen yükselir, bazen aynı kalır, bazen düşer. Bu tutarsız sonuç rastlantısal değildir: service worker, belirli koşullarda ve doğru stratejiyle uygulandığında anlamlı fark yaratır; yanlış yapılandırıldığında ise performansı iyileştirmek yerine karmaşıklık katmanı ekler.
Temel yanılgı, service worker'ı otomatik hız sağlayan bir araç olarak görmektir. Oysa service worker bir kural yazma ortamıdır. Hangi isteklerin cache'ten, hangilerinin ağdan karşılanacağını siz belirlersiniz. Bu kurallar yoksa ya da tutarsızsa kazanım da yoktur. Kurallar doğruysa, tekrarlayan ziyaretlerde belgelenmiş performans iyileşmeleri elde edilebilir.
Bu yazı service worker'ın nasıl çalıştığını, hangi stratejilerin ne zaman anlamlı olduğunu ve hangi durumlarda hiç eklememek gerektiğini ele alıyor. Teknik mekanizmaları anlamak, doğru kararı vermenin önkoşuludur.
Service worker'ın sayfayla ilişkisi ve konumu
Service worker, sayfanın JavaScript ortamının dışında çalışan ayrı bir thread'dir. Sayfayla DOM üzerinden doğrudan iletişim kuramaz; mesaj kanalları aracılığıyla haberleşir. Bu ayrım kasıtlıdır: service worker, sayfa yüklenmeden önce ve sayfa kapandıktan sonra da hayatta kalabilir. Tarayıcı onu arka planda çalışır durumda tutar.
Konumu itibarıyla sayfayla ağ arasında bir proxy görevi görür. Sayfanın yaptığı her fetch isteği — görsel, script, CSS, API çağrısı — service worker'ın fetch event handler'ından geçebilir. "Geçebilir" diyoruz çünkü hangi isteklerin yakalanacağı, service worker'ın scope'una ve yazılan kurallara bağlıdır. Kayıtlı bir scope dışındaki istekler service worker'a ulaşmaz.
install / activate / fetch yaşam döngüsü
Service worker ilk kez kaydedildiğinde install aşaması başlar. Bu aşamada genellikle kritik kaynaklar önceden cache'e alınır. install başarıyla tamamlanana kadar service worker activate olmaz; eski service worker hâlâ aktiftir. Bu geçiş mekanizması, güncelleme sırasında bozuk bir state yaşanmasını engeller.
activate aşamasında eski cache versiyonları temizlenir ve service worker kontrolü devralmaya hazır hale gelir. Ancak mevcut açık sekmelerdeki sayfalar hemen yeni service worker'a geçmez; sekme yenilenene kadar eski service worker aktif kalır. Bu davranış bazen karışıklığa yol açar: güncelleme yapıldı ama değişiklikler görünmüyor. fetch event handler, activate tamamlandıktan sonra devreye girer. Artık gelen tüm network istekleri yakalanabilir, yönlendirilebilir.
fetch interceptor mantığı: her isteği durdurma gücü
Service worker'ın en güçlü özelliği fetch event'tir. Scope dahilindeki her HTTP isteği bu handler'a düşer. Handler içinde isteğe ne yapılacağına karar verilir: cache'ten yanıt döndür, ağa ilet, her ikisini birden dene, ya da tamamen farklı bir yanıt üret.
Bu güç beraberinde sorumluluk getirir. Handler yanlış yazılırsa ya da hata fırlatırsa istek başarısız olabilir. Service worker'sız bir sayfada başarısız olan istek hata döndürür; service worker'lı bir sayfada hatalı bir handler tüm network trafiğini kesebilir. Bu nedenle fetch handler'ların hata yönetimi eksiksiz olmalı, her kod yolunda ya bir yanıt döndürülmeli ya da ağa düşülmelidir.
Cache API: tarayıcı cache'inden farkı
Service worker'ın kullandığı Cache API, tarayıcının HTTP cache'inden farklı bir depolama alanıdır. Tarayıcı cache'i Cache-Control header'larına göre otomatik çalışır; siz yalnızca direktifleri yazarsınız, geri kalanını tarayıcı yönetir. Cache API ise programatik bir arayüzdür: hangi kaynakların cache'e alınacağını, ne zaman güncelleneceğini ve ne zaman silineceğini kodla kontrol edersiniz.
Bu kontrol esneklik sağlar. Tarayıcı cache'i bir kaynağı güncellemenize izin vermez; Cache API ile istediğiniz anda istediğiniz kaynağı cache'e yazabilir ya da silebilirsiniz. Öte yandan bu esneklik, yönetim sorumluluğunu da getirir. Cache API'de depolanan veriler tarayıcı tarafından otomatik temizlenmez; eski versiyonları temizlemek service worker kodunun görevidir. Bu temizlik yapılmazsa kullanıcının depolama alanı gereksiz veriyle dolar.
Hangi kaynak tipleri için anlamlı fark yaratır
Her kaynak tipi için service worker cache'i aynı değeri üretmez. Versiyonlanmış statik varlıklar — content hash'li JavaScript ve CSS dosyaları, fontlar, görseller — service worker cache'inin en yüksek değer ürettiği kaynaklardır. Bu dosyalar değişmez; bir kez cache'e alındıktan sonra tekrarlayan ziyaretlerde ağa çıkılmadan anında döndürülebilir.
HTML sayfaları daha dikkatli değerlendirilmelidir. Stale bir HTML belgesi, güncel olmayan script ve CSS URL'leri taşıyabilir; bu durum beklenmedik davranışlara yol açar. API yanıtları kişiselleştirilmiş veri içeriyorsa cache'lenmesi uygun değildir. Görsel ve font dosyaları değişmediği sürece cache-first stratejisi için mükemmel adaydır. İsteklerin büyük bölümü bu kategoriye giriyorsa service worker anlamlı kazanım sağlar; aksi halde kazanım sınırlı kalır.
Cache-first stratejisi ve ne zaman doğrudur
Cache-first stratejisinde service worker önce Cache API'yi kontrol eder. Kaynak orada bulunuyorsa doğrudan döndürülür; ağa hiç gidilmez. Kaynak cache'te yoksa ağdan alınır ve ileriki istekler için cache'e yazılır. Bu strateji tekrarlayan ziyaretlerde en yüksek hız kazancını üretir: kaynak ağa çıkmadan, yalnızca yerel depolama gecikmesiyle gelir.
Doğru uygulandığı durumlar nettir: sık değişmeyen ve URL'si sabit kalan varlıklar. Fontlar, logolar, büyük arka plan görselleri bu gruba girer. Değişme sıklığı düşük sayfalar — sıkça güncellenmeyen "Hakkımızda" veya "İletişim" sayfaları — da cache-first için düşünülebilir. Ama sık güncellenen içerik için bu strateji kullanıcıya eski veriyi sunar. Cache hit her zaman iyi değildir; doğru içerikteki hit iyidir.
Network-first stratejisi ve dinamik içerik
Network-first stratejisinde önce ağa gidilir. Ağ başarılı yanıt verirse hem kullanıcıya iletilir hem de cache güncellenir. Ağ başarısız olursa — bağlantı kesik, sunucu yanıt vermiyorsa — cache'teki son versiyon fallback olarak döndürülür. Bu strateji sık değişen içerikler için uygundur: haber akışları, kullanıcıya özel veriler, günlük güncellenen sayfalar.
Dezavantajı, her istekte ağ gecikmesinin yaşanmasıdır. Cache-first'in sunduğu anında yanıt avantajı burada yoktur. Ama içerik doğruluğu öncelikliyse bu trade-off kabul edilebilir. Network-first ile cache-first'i aynı service worker içinde farklı kaynak tipleri için birlikte kullanmak mümkündür; bu hibrit yaklaşım çoğu gerçek dünya senaryosuna daha iyi oturur.
stale-while-revalidate service worker ile uygulandığında
HTTP header düzeyindeki stale-while-revalidate sunucu tarafında yapılandırılır. Service worker ise aynı mantığı uygulama kodunda tam kontrol altında uygulayabilir. Fetch handler içinde önce cache'ten yanıt döndürülür, ardından arka planda ağdan güncelleme yapılır ve cache yenilenir. Kullanıcı eski veriyi anında alır; bir sonraki ziyarette güncel veriyi görür.
Bu yaklaşım özellikle TTFB'nin önemli olduğu sayfalarda değerlidir. Cache'ten gelen yanıt ağ gecikmesi olmaksızın gelir, TTFB pratikte sıfıra yaklaşır. Arka plan güncellemesi kullanıcıyı bekletmez. Tek risk, cache'teki verinin ne kadar süre eskiyebileceğidir; güncelleme sıklığına göre bu kabul düzeyi değişir.
Offline deneyimi: service worker olmadan mümkün değil
Bağlantı kesildiğinde standart bir web sitesi çalışmayı durdurur. Tarayıcı "internet bağlantısı yok" sayfasını gösterir. Service worker bu senaryoyu kökten değiştirir: önceden cache'e alınmış sayfalar ve kaynaklar bağlantı olmadan da sunulabilir. Kullanıcı bir haber makalesini okuyrken bağlantısı kesilirse sayfa çalışmaya devam eder.
Offline deneyimi service worker'ın en özgün katkısıdır. Tarayıcı HTTP cache'i bu davranışı sağlayamaz; cache direktifleri bağlantı kesildiğinde işlevsiz kalır. Service worker ise fetch event'i aracılığıyla ağ hatalarını yakalayıp cache'ten fallback sunar. Bu özellik bir performans iyileştirmesi değil, bir erişilebilirlik katmanıdır. Zayıf ya da kesintili bağlantıyla gezinen kullanıcılar için somut değer üretir.
Background sync: bağlantı kesildiğinde ne olur
Kullanıcı çevrimdışıyken bir form doldurur ve gönderir. Standart bir sitede bu istek başarısız olur ve veri kaybolur. Background Sync API ile service worker bu isteği kuyruğa alır; bağlantı yeniden kurulduğunda isteği otomatik olarak yeniden gönderir. Kullanıcı uygulamayı kapatmış olsa bile — tarayıcı açık kaldığı sürece — senkronizasyon gerçekleşir.
Bu mekanizma kesintili bağlantı koşullarında form gönderimini, yorum bırakmayı veya beğeni gibi hafif etkileşimleri güvenilir hale getirir. Performans anlamında doğrudan hız kazancı sağlamaz ama kullanıcı deneyimi üzerindeki etkisi, zayıf ağ koşullarında belirgindir. Background Sync desteği tüm tarayıcılarda henüz standart değildir; kullanmadan önce hedef kitle tarayıcılarında destek durumu kontrol edilmelidir.
Push notification'ın performans maliyeti
Service worker push bildirimleri için de kullanılır. Sunucu bir push mesajı gönderdiğinde service worker uyandırılır ve bildirimi kullanıcıya iletir; sayfa açık olmak zorunda değildir. Bu özellik, service worker'ın arka planda hayatta kalma kapasitesini farklı bir amaç için kullanır.
Performans perspektifinden değerlendirildiğinde push notification'ın doğrudan sayfa hızına etkisi yoktur. Ancak push event handler'ları içinde yapılan ağ istekleri veya cache güncellemeleri, açık sayfalarla kaynak rekabeti yaratabilir. Özellikle service worker içinde push event'e yanıt olarak büyük veri çekme işlemleri yapılıyorsa bu dikkatle ele alınmalıdır. Push notification service worker'a eklenebilir; ama bu özellik performans gerekçesiyle değil, kullanıcı katılımı gerekçesiyle değerlendirilmelidir.
Service worker'ın kendi maliyeti: kurulum ve güncelleme
Service worker'ın ilk kurulum aşaması — install event — ek network istekleri içerebilir. Precache listesindeki tüm kaynaklar bu aşamada indirilir. Kullanıcı siteye ilk kez geldiğinde sayfa yüklenirken aynı anda precache de çalışır; bu durum bant genişliği rekabeti yaratır ve ilk ziyaretin biraz daha ağır olmasına yol açar.
Güncelleme aşamasında da benzer bir maliyet söz konusudur. Yeni bir service worker dosyası tespit edildiğinde tarayıcı onu indirir ve install eder. Eski service worker aktif sekmeleri kapatana kadar bekler. Bu süreç, mevcut kullanıcıların oturumunu etkilemese de arka planda ek kaynak tüketimine neden olur. Precache listesini küçük tutmak, yalnızca gerçekten kritik kaynakları dahil etmek bu maliyeti yönetmenin temel yoludur. JavaScript maliyetini minimize etme mantığının benzeri burada da geçerlidir: az ve öz, fazla ve ağır'dan iyidir.
Ne zaman eklememek gerekir
Service worker her site için doğru seçim değildir. Tekil ziyaret ağırlıklı siteler — bir landing page, kampanya sayfası veya yönlendirme sayfası — tekrarlayan ziyaret olmadığı için cache stratejisinden anlamlı bir kazanım elde edemez. Service worker kurulum maliyeti ödenir ama karşılığı gelmez.
Oturum yönetimi karmaşık, sık güncellenen ve kişiselleştirilmiş içerik ağırlıklı siteler de dikkatli olmalıdır. Yanlış cache stratejisi eski içerik sunulmasına ya da farklı kullanıcıların birbirinin cache'lenen verilerini görmesine yol açabilir. Karmaşıklığı yönetecek kaynak yoksa, testleri yetersizse, service worker güncelleme süreçleri anlaşılmamışsa — o zaman eklememek, eklemekten daha güvenlidir. Service worker hatalı çalıştığında hata ayıklama süreci tarayıcı network sorunlarından çok daha karmaşık olabilir.
Gerçek performans kazancının ölçülmesi
Service worker'ın etkisini ölçmenin en doğrudan yolu tekrarlayan ziyaret metriklerini karşılaştırmaktır. Chrome DevTools'ta "Disable cache" seçeneğini kapatıp sayfayı yenilemek service worker üzerinden gelen yanıtları gösterir. Network sekmesinde "(Service Worker)" olarak işaretlenen yanıtlar cache'ten geliyordur; bunların yükleme süreleri ağdan gelen yanıtlarla kıyaslanabilir.
Gerçek kullanıcı verisi daha güvenilir bir tablo sunar. İlk ziyaret ile tekrarlayan ziyaret metriklerini ayrı ayrı takip etmek — LCP, TTFB ve toplam yükleme süresi üzerinden — service worker'ın hangi segmentte fark yarattığını gösterir. Service worker cache'inin devreye girmediği ilk ziyaretlerde iyileşme beklenmez; kazanım tekrarlayan ziyaretlerde ortaya çıkar. Bu ayrımı yapmadan ölçüm yapmak, service worker'ın gerçek etkisini ya abartır ya da küçümser.
Service worker bir performans aracı olduğu kadar bir mimari karardır. Doğru stratejilerle uygulandığında tekrarlayan ziyaretlerde kaynak yüklerini ortadan kaldırır, kesintili bağlantılarda çalışmaya devam eden sayfalar sağlar ve kullanıcıya kontrol altındaki bir cache deneyimi sunar. Bu kazanımlar anlamlıdır ama koşulludur.
Cache stratejisi kaynak tipine göre bilinçle seçilmeli, precache listesi dar tutulmalı ve güncelleme davranışı test ortamında doğrulanmalıdır. Service worker'ın nerede devreye girdiğini, neyi cache'lediğini ve ne zaman ağa çıktığını anlamak, onu doğru kullanmak için yeterlidir.
Soru "service worker ekleyeyim mi?" değil "hangi kaynak tiplerinde hangi stratejiyi uygulayacağım ve bunu nasıl test edeceğim?" olmalıdır. Bu soruya yanıt vermeden eklenen bir service worker, en iyi ihtimalle etkisiz kalır; en kötü ihtimalle beklenmedik sorunlara kapı aralar.