İçeriğe geç

Tarayıcı Önbelleği — Yeni Sürümü Yayına Aldın, Müşteri Neden Hâlâ Eskisini Görüyor?

Orta 9 dk Sık karşılaşılır

Önce şunu oku: Tarayıcı Nasıl Çizer — Animasyon Neden Takılıyor?

30 saniyede özet

Tarayıcı dosyaları önbellekte tutar ve sunucunun söylediği kadar süre bir daha sormaz. HTML'i her seferinde ETag ile sor, adında içerik özeti olan dosyaları uzun süre sakla, hassas veriyi hiç saklatma.

Bankanın ücret broşürünü bir kez alıp evde saklıyorsun. Her seferinde şubeye gitmek yorucu, ama evdeki broşüre çok uzun süre güvenirsen fiyatlar değiştiğinde haberin olmaz.

  1. Bayt: Ödeme ekranındaki hatayı düzelttim, yeni sürüm yayında!

  2. Sen: Müşteri hâlâ aynı hatayı görüyor. Bir başkası ise boş beyaz bir sayfa.

  3. Bayt: Sunucuda yeni kod var. Ben de görüyorum. Onlar neden görmüyor?

  4. Bayt: Belki sunucuya hiç sormuyorlar. Tarayıcı ne kadar süre sormamasını söylemiştik?

Tarayıcı ne zaman sormaz?

Sunucu her dosyayla birlikte bir Cache-ControlSunucunun bir cevapla gönderdiği başlık: tarayıcının bu cevabı saklayıp saklamayacağını ve ne kadar süre sormadan kullanacağını söyler.Sözlükte gör → başlığı gönderir. max-age=86400 “bu dosyayı 24 saat boyunca bana sormadan kullan” demektir.

Bu süre içinde tarayıcı sunucuya hiç gitmez. Sayfa çok hızlı açılır, ama sen bu arada yeni sürüm yayına alsan bile müşteri eskisini görür.

Kafam karıştı, daha basit anlat

Cache-Control, tarayıcıya bir dosyayı ne kadar süre sormadan kullanacağını söyler. O süre bitmeden yeni sürüm görünmez.

Hızlı kontrolBaşlangıç

Cache-Control: max-age=86400 tarayıcıya ne söyler?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

HTML 24 saat önbellekte. Yeni sürüm yayına alındı. Müşteri bir saat sonra sayfayı açtı. Ne görür?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Sor, ama ucuza sor

HTML'i her seferinde sunucuya soruyoruz, ama app.js'i aynı adla 24 saat önbellekte tutuyoruz. Yeni sürüm yayına alındı. Müşteri ne görür? Cevabı göster

Yeni HTML ile eski JavaScript. HTML yeni geldi, ama app.js’in adı değişmediği için tarayıcı önbellekteki eski dosyayı kullandı. Bu karışım beyaz bir sayfaya bile yol açabilir.

Baskı adı kapakta: yeni baskı, yeni broşür.
Adım adım oku
  1. Her seferinde şubeye gidip broşür almak.
  2. Evdeki eski broşür: fiyatlar değişmiş.
  3. Ekim baskısı hâlâ geçerli mi? Evet.
  4. Baskı adı kapakta: yeni baskı, yeni broşür.

ETagBir dosyanın sürümünü gösteren kısa etiket. Tarayıcı onu geri gönderip 'değişti mi?' diye sorar; değişmediyse sunucu gövdesiz bir 304 döner.Sözlükte gör →, dosyanın sürümünü gösteren kısa bir etikettir. Tarayıcı bunu geri gönderip “değişti mi?” diye sorar; değişmediyse sunucu gövdesiz bir 304 döner.

JavaScript ve CSS için daha iyisi var: dosyanın adına içerik özetiDosyanın içeriğinden hesaplanan kısa bir değer, dosya adına eklenir (app.3f9a.js). İçerik değişince ad da değişir.Sözlükte gör → koymak (app.3f9a.js). İçerik değişince ad da değişir; bu yüzden dosya bir yıl önbellekte kalabilir.

Kafam karıştı, daha basit anlat

HTML’i her seferinde ETag ile sor. Adında içerik özeti olan dosyaları uzun süre sakla.

Hızlı kontrolOrta

ETag ile yapılan bir istekte dosya değişmemişse sunucu ne döner?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Dosya adına içerik özeti koymak (app.3f9a.js) neden uzun önbelleği güvenli yapar?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kendin gör

Dört ziyaret, arada bir yayın

Tohum 621042
  1. Saat 0
  2. Saat 2
  3. Saat 4 (yayından sonra)
  4. Saat 30

Sunucuda saat 3'ten itibaren sürüm 2 var · toplam indirilen: 0 KB

Hız
Adım 0

Şu an ne oldu?

Önbellek yok

Ziyaretler saat 0, 2, 4, 30'da; saat 3'te yeni sürüm yayına alınıyor.

Görevler0/3

  • Yayından sonra müşteri hâlâ eski sürümü görsünaçık

    İpucu

    Tarayıcı sunucuya hiç sormasın.

  • Yeni HTML eski JavaScript ile çalışsınaçık

    İpucu

    HTML’i sor, ama JS adını değiştirme.

  • Her ziyaret güncel olsun, toplam indirme önbelleksizin yarısı kadar kalsınaçık

    İpucu

    Dosyanın adı içeriğini söylesin.

Olay günlüğü (0)

Henüz olay yok. Oynat veya adımla.

  1. Varsayılanla oynat. Her ziyaret güncel, ama her seferinde 208 KB indirildi.
  2. “Her şey 24 saat önbellekte” seç. Saat 4’teki ziyaret hiç istek göndermedi ve eski sürümü gösterdi.
  3. “HTML ETag ile, app.js 24 saat” seç. Saat 4’te yeni HTML eski app.js ile çalıştı.
  4. “JS adında içerik özeti” seç. Her ziyaret güncel, toplam indirme yarıya indi.
Hızlı kontrolOrta

HTML her seferinde soruluyor ama app.js aynı adla 24 saat önbellekte. Yayından sonra ne olabilir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Önbellek hiç kullanılmazsa ne olur?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Tuzaklar

no-cache ile no-store’u karıştırmak. no-cache “sakla ama her seferinde sor” demektir. Hiç saklanmaması gereken şey için no-store gerekir.

Hassas veriyi önbellekte bırakmak. Hesap bakiyesi ya da hareket listesi ortak bir bilgisayarda kalmamalı. Bu cevaplara no-store koy.

Önbelleği temizlemeyi çözüm sanmak. “Ctrl+F5 yapın” demek yalnızca o müşteriyi düzeltir. Kalıcı çözüm, başlıkları ve dosya adlarını doğru kurmaktır.

Kafam karıştı, daha basit anlat

no-cache sorarak saklar, no-store hiç saklamaz. Hassas veriye no-store koy.

Hızlı kontrolOrta

Hesap bakiyesini döndüren API cevabı için hangi başlık uygundur?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.
Derinleş · İnternet şubesi: dosya adı, başlık ve hassas veri 4 dosya · ~79 satır · ilk okumada atlayabilirsin
Proje dosyaları

web/ vite.config.ts Vite: her derlemede dosya adına içerik özeti eklenir; içerik değişmezse ad da değişmez.

web/vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
output: {
// The content hash in the name: a new build with new code gets a new URL.
entryFileNames: 'assets/[name].[hash].js',
chunkFileNames: 'assets/[name].[hash].js',
assetFileNames: 'assets/[name].[hash][extname]',
},
},
},
});

src/main/java/com/bank/web/ WebCacheConfig.java Spring yapılandırması: özetli dosyalar bir yıl, HTML ise her seferinde ETag ile sorulur.

src/main/java/com/bank/web/WebCacheConfig.java
@Configuration
class WebCacheConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Hashed names never change content, so a year is safe.
registry.addResourceHandler("/assets/**")
.addResourceLocations("classpath:/static/assets/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic());
// The HTML names the bundles: the browser must ask every time.
registry.addResourceHandler("/index.html")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.noCache());
}
@Bean
FilterRegistrationBean<ShallowEtagHeaderFilter> htmlEtags() {
var filter = new FilterRegistrationBean<>(new ShallowEtagHeaderFilter());
filter.addUrlPatterns("/index.html"); // unchanged HTML answers 304 with no body
return filter;
}
}

src/main/java/com/bank/account/ BalanceController.java Bakiye: hassas cevap hiçbir yerde saklanmaz.

src/main/java/com/bank/account/BalanceController.java
@RestController
@RequestMapping("/api/accounts")
class BalanceController {
private final BalanceService balances;
BalanceController(BalanceService balances) {
this.balances = balances;
}
@GetMapping("/{iban}/balance")
ResponseEntity<Balance> balance(@PathVariable String iban) {
return ResponseEntity.ok()
.cacheControl(CacheControl.noStore()) // never on disk, never in a shared cache
.body(balances.of(iban));
}
}

src/test/java/com/bank/web/ WebCacheConfigTest.java Test: başlıkları ve 304 cevabını uygulamanın kendisi üzerinde kontrol eder.

src/test/java/com/bank/web/WebCacheConfigTest.java
@SpringBootTest
@AutoConfigureMockMvc
class WebCacheConfigTest {
@Autowired MockMvc mvc;
@Test
void hashedBundlesAreCachedForAYear() throws Exception {
mvc.perform(get("/assets/app.3f9a.js"))
.andExpect(header().string("Cache-Control", containsString("max-age=31536000")));
}
@Test
void unchangedHtmlAnswers304() throws Exception {
String etag = mvc.perform(get("/index.html")).andReturn().getResponse().getHeader("ETag");
mvc.perform(get("/index.html").header("If-None-Match", etag))
.andExpect(status().isNotModified());
}
@Test
@WithMockUser
void balanceIsNeverStored() throws Exception {
mvc.perform(get("/api/accounts/TR01/balance"))
.andExpect(header().string("Cache-Control", "no-store"));
}
}

Kendini sına

Şimşek turu1/4

Cache-Control: no-cache, dosyanın hiç saklanmayacağı anlamına gelir.

Soru 1/3İleri

Müşteriye 'Ctrl+F5 yapın' demek neden kalıcı bir çözüm değildir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aklında kalacak üç şey

  1. 1 Cache-Control bir dosyanın ne kadar süre sunucuya sorulmadan kullanılacağını söyler. HTML uzun süre önbellekte kalırsa, yayından sonra müşteri eski sürümü görür.
  2. 2 ETag ile tarayıcı 'bu dosya değişti mi?' diye sorar; değişmediyse sunucu gövdesiz bir 304 döner. Doğruluk korunur, indirilen veri küçülür.
  3. 3 Adında içerik özeti olan dosya (app.3f9a.js) değişince adı da değişir. Böylece bir yıl önbellekte kalabilir ve yeni sürüm yine anında gelir.
Sonraki kapı Biri sana havale gönderdi, açıklamaya garip bir şey yazdı. Sen sadece hesap hareketlerine baktın. Oturumun nasıl çalındı? XSS — Havale Açıklamasına Yazılan Kod Neden Müşterinin Sayfasında Çalışır? · 9 dk

4 kart sonraki derste seni bekliyor

0/4 kart bu dersten toplandı

Bu dersin üstüne kurulanlar

Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.