Webpack İpuçları #4: Content Hash ile Bundle Dosyalarının Tarayıcı Önbelleğinde Kalmasını Önlemek

Tuğsan Ünlü
4 min readSep 12, 2021

Webpack serisindeki bir önceki yazı: Webpack İpuçları #3: Terser Plugin ile Canlı Ortama Çıkarken Konsol Loglarını Temizlemek

Motivasyon

Geliştirdiğimiz web projelerinde kullandığımız asset’leri (JS, CSS vb. kaynaklar) projelerin mimarisine göre farklı yöntemlerle sayfalara dahil ediyoruz. Bu bazen tüm asset’lerin bir JavaScript dosyası içerisinde bundle edilmesiyle oluyor. Bazen de kullanıcı deneyimi gibi endişelerle CSS dosyalarının ayrıştırılmasıyla. Fakat her halükârda kendi sunucularımızda veya uzak bir sunucuda yer alan bir veya birkaç dosyanın sayfamız tarafından talep ediliyor olması gerekiyor.

Aşağıdaki gibi bir kullanım, JavaScript kaynakları için bunun en temel hâli.

javascript dosyasının sayfaya bağlanması

Örnekteki bundle.js dosyası, ilk isteğin ardından uzak sunucudan talep edilip indirildikten sonra tarayıcı önbelleğine alınıyor. Sonraki isteklerde uzak sunucuya gidilmeden önbellekteki dosya sanki uzak sunucudan geliyormuşçasına işleniyor.

önbelleğe alınan dosyanın sunulması

Ta ki ilk isteğin yanıtında Cache-Control başlığıyla belirtilen önbellek süresi dolana kadar.

http yanıtındaki önbellek başlıkları

İlgili dosyanın, önbellek süresi bitene kadar değiştirilip kullanıcıya tekrar sunulması gerekmediği senaryolarda harika bir performans optimizasyonu bu. Bir kere geliştirici için hiçbir maliyeti yok. Tüm operasyonu tarayıcı tek bir başlığa bakarak hallediyor. Önbelleğe alma, önbellek süresi kontrolü vs. tümü tarayıcının sorumluluğunda.

Kötü Senaryo

Üstteki kapsama girmeyen senaryoya örnek olarak, projede kritik bir hata düzeltmesi yaptık diyelim. Uzak sunucudaki dosyayı artık hataya mahal vermeyecek şekilde güncelledik. Fakat kullanıcının tarayıcısındaki önbellek süresi henüz dolmadığı için tarayıcı dosyayı uzak sunucudan almak yerine hâlâ diskteki hatalı hâlini işleyecek.

İptidai Yöntem

Önceleri bunun önüne geçmek için oldukça iptidai bir yöntemle dosya için bir sürüm tanımlaması yapıyorduk. Tarayıcı da önbelleğe aldığı dosyanın sürümüyle talep edilen yeni dosyanın sürümünü eşleştiremediği için uzak sunucudan dosyanın güncel hâlini yeniden talep ediyordu.

javascript dosyasını sürüm ile sayfaya bağlamak

Önceki yazılarda da değinmeye çalıştığım gibi bu yöntemin de en büyük handikapı kontrolün insana bırakılmasının neticesinde unutulması oluyor. Gerçek hayat senaryolarında, sürüm numarasının güncellenmesinin unutulması, herkesin kendi meşrebince bir sürüm numarası vermek istemesi, yanlış veya eksik dosyaların sürümlenmesi gibi sorunları beraberinde getiriyor bu yöntem.

HtmlWebpackPlugin ve Content Hash

Webpack, HtmlWebpackPlugin eklentisiyle birlikte oluşturduğu bundle dosyaları için oldukça pratik ve garantili bir yöntemle bu sorunun önüne geçiyor.

Bilindiği üzere hash (özet), bir verinin Bcrypt vb. algoritmalarla tek yönlü olarak şifrelenerek özetinin çıkarılması anlamına geliyor. Bu sayede ilgili verinin bütünlüğünü koruyup korumadığını içeriğini açıkça karşılaştırmadan kontrol edebiliyoruz.

HtmlWebpackPlugin, HTML dosyaları oluşturabilen, oluşturduğu dosyalara istenilen Webpack çıktılarını (chunk) bağlayabilen bir eklenti. Webpack’in content hash özelliği sayesinde proje build olurken bundle dosyalarının hash’lerini çıkarıyor. Çıkardığı hash’leri de bundle dosyalarının isimlerine ekleyerek bir nevi dosya ismiyle sürümleme yapıyor.

content hash için temel webpack yapılandırması

Aşağıdaki örnekte dosya isminden noktayla ayrılan 20 hanelik alan dosya içeriğinin hash’ini temsil ediyor.

content hash ile oluşturulan bundle dosyasının sayfaya bağlanması

Dosya içeriği değişmediği sürece hash’i de değişmeyeceği için proje ne kadar build olursa olsun dosyalar aynı isimlerle sunulmaya devam ediyor. Fakat dosyada tek bir karakter dahi değişse hash’i de değişeceği için build sırasında dosyanın ismi de değişmiş ve tarayıcının önbelleğine aldığı eski dosya artık kullanılmaz hâle gelmiş oluyor.

Sonuç

Content hash özelliği özellikle çok sık deploy edilen dinamik projelerde işleri oldukça kolaylıyor. Operasyonu insanın üzerinden aldığı için elle yapılan müdahelelere de gerek bırakmıyor. Module bundler olarak Webpack kullanan Create React App gibi birçok boilerplate hâlihazırda varsayılan olarak bu özelliği açık getiriyor. Fakat Webpack yapılandırmasının elle yapıldığı veya boilerplate kullanılsa dahi bağımlılıkların eject edildiği senaryolarda content hash özelliğini elle aktif etmek gerekebiliyor.

Kaynaklar

--

--