Cache ve Strateji
Immutable Cache Ne Zaman Kullanılır?
Bir JavaScript dosyası için tarayıcı her sayfada bir doğrulama isteği gönderiyor. Dosya değişmemiş; sunucu 304 döndürüyor. Performans açısından bakıldığında bu iyi görünür — aktarım yok, gecikme minimal. Ama bu doğrulama isteğinin hiç gönderilmemesi de mümkündü. Sunucuya gidip gelen o küçük tur, yüzlerce kaynak için binlerce kullanıcı üzerinde biriktiğinde göz ardı edilmeyecek bir yük oluşturur.
immutable direktifi tam bu ihtiyaç için tasarlanmıştır. Cache-Control başlığına eklenen bu sözcük tarayıcıya şunu söyler: "Bu kaynağın TTL'i dolana kadar doğrulama isteği gönderme. Elindeki versiyonun hâlâ geçerli olduğunu sana garanti ediyorum." Tarayıcı bu garantiyi aldığında koşullu istek göndermez, ağa çıkmaz, kaynağı doğrudan cache'ten kullanır.
Bu garanti güçlüdür — ve tehlikelidir. Doğru koşullarda uygulandığında gereksiz ağ trafiğini ortadan kaldırır. Yanlış koşullarda uygulandığında kullanıcılar eski içeriği görmeye devam eder ve bunu düzeltmenin tarayıcı tarafında neredeyse hiçbir yolu kalmaz. Direktif nerede ve nasıl kullanılacağını belirleyen bu ince sınır, konunun tamamını özetler.
immutable direktifi ne anlama gelir
Cache-Control: max-age=31536000, immutable başlığı iki şey söyler. max-age=31536000 kaynağın bir yıl boyunca geçerli sayılacağını belirtir. immutable ise bu süre içinde tarayıcının doğrulama isteği göndermeyeceğini, yani If-None-Match veya If-Modified-Since header'ı taşıyan bir koşullu istek oluşturmayacağını garanti eder.
Normalde TTL'i dolmamış bir kaynak için tarayıcı cache'i kullanır — bu zaten beklenen davranıştır. immutable'ın farklı kıldığı durum, kullanıcının sayfayı yenilediği andır. Standart bir yenileme (F5) TTL'den bağımsız olarak tüm kaynaklar için doğrulama isteği tetikler. immutable eklenmiş kaynaklar bu yenileme davranışından muaf tutulur; tarayıcı yenileme sırasında bile ağa çıkmaz.
max-age olmadan immutable çalışmaz
immutable tek başına geçerli bir direktif değildir. Mutlaka max-age ile birlikte kullanılır. max-age değeri olmadan immutable'ın hangi süre boyunca geçerli olduğu belirsiz kalır; tarayıcılar bu durumu farklı yorumlayabilir ya da direktifi tamamen görmezden gelebilir.
max-age değeri ne kadar olmalı? immutable genellikle çok uzun TTL değerleriyle, tipik olarak bir yılla (31536000 saniye) birlikte kullanılır. Bu süre içinde içeriğin hiç değişmeyeceğinden emin olunması gerekir. Eğer kaynak bir noktada güncellenecekse URL'sinin de değişmesi şarttır — aksi takdirde tarayıcı eski versiyonu bir yıl boyunca kullanmaya devam eder ve bunu düzeltemenin hiçbir mekanizması yoktur.
Hash tabanlı dosya adıyla ilişkisi
immutable'ın güvenli biçimde kullanılabilmesi için içerik değiştiğinde URL'nin de değişmesi gerekir. Bu şartı karşılamanın standart yöntemi, dosya adına içerik hash'i eklemektir: app.a3f8b2c1.js veya styles.4d7e9f2a.css gibi. Dosyanın içeriği değiştiğinde build süreci yeni bir hash üretir, dosya adı değişir, dolayısıyla yeni bir URL oluşur.
Bu kombinasyonun mantığı tutarlıdır. app.a3f8b2c1.js URL'sini bir kez görmüş tarayıcı, immutable direktifi sayesinde bir yıl boyunca ağa çıkmadan bu dosyayı cache'ten sunar. Yeni bir deploy geldiğinde URL app.7b1c4e3d.js olur; tarayıcı bunu daha önce görmemiştir, dolayısıyla bir kez indirir. Eski URL artık hiç istenmez. Doğrulama isteği, 304 yanıtı, cache geçersizleştirme — bunların hiçbirine gerek kalmaz. Sistem hem hızlı hem de doğrudur.
Hangi kaynak tipleri için uygundur
immutable'ın güvenli çalıştığı kaynak tipleri versiyonlanmış statik varlıklardır. Bir build sistemi tarafından üretilen ve dosya adına content hash eklenen CSS, JavaScript, görsel ve font dosyaları bu kategoriye girer. Webpack, Vite, Parcel ve benzeri araçların çıktısı genellikle bu yapıya uygundur; her dosya, içeriğine göre benzersiz bir hash taşır.
Bu dosyaların ortak özelliği, bir kez yayınlandıktan sonra değişmemesidir. Güncelleme yapılacaksa yeni hash ile yeni bir dosya oluşturulur; eski dosya değişmeden kalır. immutable, tam olarak "bu URL'nin arkasındaki içerik asla değişmeyecek" garantisini verilen durumlar için tasarlanmıştır. Kaynak bu garantiyi karşılıyorsa immutable uygulanabilir; karşılamıyorsa uygulanmamalıdır.
HTML sayfalarında immutable neden yanlıştır
HTML dosyaları immutable için uygun değildir. Bir sayfa güncellendiğinde genellikle aynı URL kullanılmaya devam eder; içerik değişse de adres değişmez. immutable eklenmiş bir HTML dosyası için tarayıcı TTL dolana kadar hiç doğrulama yapmaz. Yeni içerik deploy edilmiş olsa bile kullanıcılar eski versiyonu görmeye devam eder.
Bu sorun kullanıcı tarafında çözülemez. Cache'i temizlemek veya hard refresh yapmak ise yalnızca teknik bilgiye sahip kullanıcıların başvurabileceği yöntemlerdir. HTML dosyalarına immutable eklenmemeli; bunun yerine kısa TTL veya no-cache direktifi kullanılmalıdır. no-cache, içeriğin her istekte doğrulama mekanizmasından geçmesini sağlar; içerik değişmemişse 304 döner, değişmişse yeni versiyon gelir.
Dinamik içerik ve API yanıtlarında risk
Kişiselleştirilmiş içerik, oturum durumuna bağlı yanıtlar ve sık güncellenen API çıktıları immutable için kesinlikle uygun değildir. Bu kaynaklar kullanıcıdan kullanıcıya veya istekten isteğe farklılık gösterir; sabit bir URL arkasında değişken içerik barındırır.
immutable bu tür kaynaklar için uygulandığında, tarayıcı cache'teki ilk yanıtı sonraki tüm istekler için kullanır. Kullanıcı oturumunu kapattığında bile bir sonraki kullanıcı önceki kişinin cache'lenen yanıtını görebilir — eğer aynı tarayıcı oturumu paylaşılıyorsa. Gerçek shared cache ortamlarında (CDN, proxy) bu risk çok daha ciddi sonuçlar doğurabilir. immutable yalnızca içeriğin URL ile tam olarak örtüştüğü, URL değiştiğinde içeriğin de değiştiği durumlar için güvenlidir.
immutable olmadan versiyonlamanın maliyeti
Hash tabanlı dosya adı kullanan bir site, immutable eklemeden uzun max-age ile çalışıyorsa ne olur? İlk yüklemede tarayıcı dosyayı indirir ve cache'ler. Sonraki ziyaretlerde TTL dolmadığı sürece cache'ten kullanır — bu doğru çalışır. Ama kullanıcı sayfayı yenilediğinde tarayıcı standart davranışa döner: tüm kaynaklar için doğrulama isteği gönderir.
Her doğrulama isteği bir ağ turu demektir. 304 yanıtı hızlı gelse de DNS çözümlemesi, TCP bağlantısı veya en azından TLS üzerinde bir round-trip yaşanır. Bir sayfada onlarca versiyonlanmış kaynak varsa ve kullanıcı sayfayı sık yeniliyorsa bu maliyet birikir. Hit oranı yüksek bir yapıda bile bu doğrulama istekleri gereksiz yere origin'e ulaşır. immutable bu isteklerin tamamını keser.
CDN'lerin immutable direktifini yorumlama biçimi
immutable, HTTP/1.1 spesifikasyonunda tanımlı resmi bir direktif değildir; RFC 8246 ile ayrıca tanımlanmıştır. Bu nedenle CDN ve proxy desteği evrensel değildir. Cloudflare ve Fastly gibi büyük CDN'ler immutable'ı anlayıp ona göre davranır: kaynak için doğrulama isteği oluşturmaz, TTL dolana kadar origin'e gitmeyi önler.
Desteklemeyen CDN'ler ise bu direktifi yalnızca tarayıcıya ileten bir header olarak iletir ya da tamamen yok sayar. CDN davranışı, kullanılan sağlayıcının dokümantasyonundan kontrol edilmelidir. CDN'nin immutable'ı desteklemediği durumlarda kazanım yalnızca tarayıcı düzeyinde kalır; CDN katmanında hâlâ koşullu istek trafiği oluşabilir. Bu durum performansı sıfırlamaz ama immutable'ın tam potansiyelinin kullanılamadığı anlamına gelir.
stale-while-revalidate ile farkı
Her ikisi de kullanıcıyı bekleme süresinden korumaya yönelik mekanizmalardır ama farklı biçimlerde çalışır. stale-while-revalidate, TTL dolduğunda süresi geçmiş içeriği anında döndürür ve arka planda yenileme yapar. Kaynak belirli aralıklarla güncellenir; her güncelleme sonrasında arka planda yeni bir versiyon çekilir. İçerik her zaman en güncel değildir ama kullanıcı gecikme görmez.
immutable ise farklı bir senaryoya aittir: kaynak TTL boyunca hiç değişmeyecektir. Arka planda doğrulama yapılmaz çünkü yapılmasına gerek yoktur. stale-while-revalidate "içerik değişebilir, ama kullanıcıya gecikme yaşatmadan güncelle" derken, immutable "içerik kesinlikle değişmez, ağa çıkma" der. Hangisinin kullanılacağı kaynağın değişme sıklığına ve URL stratejisine göre belirlenir.
Yanlış kullanımın tespiti ve düzeltmesi
immutable yanlış uygulanmış bir kaynakta sorun ortaya çıktığında — kullanıcı güncellenen içeriği göremiyorsa — düzeltme seçenekleri oldukça sınırlıdır. Tarayıcının cache'ini temizlemek işe yarar ama bu yalnızca o kullanıcı için geçerlidir. Diğer kullanıcılar için yapılabilecek hiçbir şey yoktur; onlar TTL dolana kadar eski versiyonu görmeye devam eder.
Chrome DevTools'ta Network sekmesinde bir kaynağın response header'ları incelendiğinde Cache-Control: max-age=31536000, immutable görünüyorsa, o URL'nin içeriğinin gerçekten sabit olduğu doğrulanmalıdır. Aynı URL üzerinden farklı içerik sunuluyorsa veya sunulabilecekse, immutable kaldırılmalı ya da URL stratejisi hash tabanlı yapıya geçirilmelidir. Yanlış bir immutable konfigürasyonu düzeltmek için en hızlı yol URL değiştirmektir — yeni URL için eski cache girişi geçersiz olur ve tarayıcı sıfırdan başlar.
Ne zaman uygulanmalı, ne zaman kaçınılmalı
immutable uygulanabilir durumlar net bir örüntü izler: build süreci tarafından üretilen, dosya adında content hash bulunan ve aynı URL'nin arkasındaki içeriğin asla değişmeyeceği kaynaklar. Versiyonlanmış JavaScript bundle'ları, içerik hash'li CSS dosyaları, fingerprintli görsel ve font dosyaları bu kapsamdadır.
Kaçınılması gereken durumlar da aynı netlikte tanımlanır: URL'si sabit ama içeriği değişebilen her kaynak. HTML sayfaları, API yanıtları, oturuma bağlı içerikler, sürüm numarası yerine tarih veya sıralı numara taşıyan dosyalar bu gruba girer. Bir kaynak için "bu URL'nin arkasındaki içerik her zaman aynı kalacak mı?" sorusunun yanıtı kesinlikle evet değilse immutable kullanılmamalıdır.
immutable direktifi dar ama kesin tanımlı bir kullanım alanına sahiptir. Build araçlarının ürettiği versiyonlanmış statik varlıklar için uygulandığında, tarayıcının gereksiz ağ trafiğini tamamen ortadan kaldıran güçlü bir optimizasyon sağlar. Tekrarlayan ziyaretlerde kaynak yenileme davranışı dahil hiçbir koşulda ağa çıkılmaz; kullanıcı her yüklemede cache'ten anında yanıt alır.
Bu optimizasyonun bedeli sıfırdır — eğer önkoşullar karşılanıyorsa. Hash tabanlı URL stratejisi zaten uygulanıyorsa, max-age değeri zaten uzun tutuluyorsa, immutable eklemek yalnızca doğrulama isteklerini keser. Ek yük yoktur, ek risk yoktur. Önkoşullar karşılanmıyorsa risk somuttur ve tersine çevrilmesi güçtür.
Bu nedenle immutable, konfigürasyona eklenmeden önce URL stratejisinin kontrol edilmesi gereken direktiflerden biridir. Doğru altyapı üzerinde çalışır; altyapıyı varsaymaz. Build sistemi hash üretiyorsa ve deploy URL'yi değiştiriyorsa, immutable bu sistemin doğal bir tamamlayıcısıdır.