CDN'de asset sürümleme: hash'leme ve cache stratejisini nasıl kurarım?
Soru
DeployerPHP ile yeni kodu canlıya alınca kullanıcının tarayıcısındaki eski CSS/JS yüzünden arayüz kırılıyor. `mix.js?id=123` gibi query string'i bazı CDN'ler göz ardı ediyor, eski sürümü servis etmeye devam ediyor. Kalıcı çözüm için asset adlarını hash'leyip (`app.a8f9b2.js`) `Cache-Control: max-age=31536000` ile CDN'e göndermek istiyorum. CI/CD'de derleme ve invalidate otomasyonunu nasıl tasarlarım?
Cevap
Kısa cevap: Query-string ile cache busting güvenilmez; kalıcı çözüm content-hash’li dosya adı (app.a8f9b2.js) — ad sadece içerik değişince değişir, gerisini cache stratejisi halleder.
Kısa cevap
Sorunun kökü şu: app.js?id=123 deseninde dosya adı hep aynı. Bazı CDN’ler query string’i cache key’inden atar ya da yok sayar, dolayısıyla id değişse de cache’teki ESKİ dosyayı servis etmeye devam eder. Cache key’ini değiştirmeniz gerekiyor — query’yi değil, adı. Aynı “önbelleği kim tazeliyor” sorusunun API tarafını edge cache ve invalidation kaydında ele almıştım.
Neden
-
Query string bir cache key garantisi değildir. Davranış CDN’e göre değişir; bazıları onu tamamen yok sayar. Adın kendisi ise her katmanda cache key’in parçasıdır.
-
İçerik hash’i doğal bir sürüm numarasıdır. Ad yalnız içerik değiştiğinde değişir; değişmediğinde aynı kalır, yani gereksiz yeniden indirme de olmaz.
-
Deploy anı bir yarış koşuludur. Yeni HTML henüz yüklenmemiş bir hash’e işaret ederse kullanıcı 404 alır; sıra yanlışsa hash’leme de kurtarmaz.
Ne yapmalı
-
Content-hash’li dosya adı kullanın.
app.a8f9b2.jsgibi; hash dosyanın içeriğinden türer. Böylece her asset’iCache-Control: public, max-age=31536000, immutableile cache’leyebilirsiniz —immutabledirektifi tarayıcıya “bunu bir daha doğrulama bile” der, gereksiz koşullu istekleri keser. -
HTML/giriş noktasını kısa ömürlü tutun. Hash’li asset’lere işaret eden HTML’i
no-cacheya da kısa TTL ile verin: HTML her zaman taze gelsin ki yeni hash’lere işaret etsin. Burayı uzun cache’lerseniz tüm zincir kilitlenir. -
CI/CD’de önce yükleyin, sonra canlıya geçin. Vite manifest’i ile hash’li çıktı üretin ve asset’leri uygulamayı canlıya almadan önce CDN’e/bucket’a yükleyin. DeployerPHP akışında bunu “symlink’i çevirmeden önce upload” adımı olarak kurun.
-
Önceki sürümün asset’lerini bir süre tutun. Deploy anında sayfası açık olan kullanıcı hâlâ eski HTML’i çalıştırıyor ve eski hash’leri ister. DeployerPHP’nin
keep_releasesmantığı bu “in-flight” kullanıcıları korur.
Sonuç: Ben olsam content-hash’li, immutable cache’li asset + kısa ömürlü HTML + canlıya-geçmeden-önce-upload üçlüsünü kurardım. Gerçek content hashing’de pratikte asset purge’üne neredeyse hiç ihtiyacınız olmaz — ad değiştiği için eski dosya zaten dokunulmadan kalır, kimse onu istemez. Tek invalidate etmeniz gereken şey HTML’dir, o da zaten kısa cache’li. Query-string busting’i tamamen bırakın.
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.