Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

HTTP cache header'larında `ETag` ve `Last-Modified` ile koşullu istekleri (304 Not Modified) nasıl etkin kıldığım

websterx

Üye
Katılım
14 Mart 2026
Mesajlar
34
Merhaba arkadaşlar, bugün başımı çok ağrıtan bir konudan bahsedeceğim. Sitemin performansını artırmak için cache'leme yapıyordum ama statik asset'lerim (CSS, JS, resimler) her seferinde sunucudan tam boyutuyla indiriliyordu. "Bu dosyalar değişmediyse neden tekrar yükleniyor?" diye düşünürken, koşullu istekler (conditional requests) ve 304 Not Modified durum kodunun gücünü yeniden keşfettim.

🔥 Sorunun Özü: Gereksiz Veri Transferi

Bir kullanıcı sitemizi ziyaret ettiğinde, tarayıcı tüm statik dosyaları önbelleğine (cache) alır. Ancak, kullanıcı sayfayı yenilediğinde veya bir sonraki girişinde, tarayıcı sunucuya "Bu dosya hala geçerli mi?" diye sormak yerine, genellikle "Bana bu dosyanın tamamını tekrar ver" şeklinde bir istek (GET) atıyordu. Bu da hem sunucu band genişliğini hem de kullanıcının sayfa yükleme süresini olumsuz etkiliyordu. İşte tam burada ETag ve Last-Modified header'ları devreye giriyor.

🔧 Çözüm: Sunucu Tarafında Doğru Header'ları Göndermek

Amacım basitti: Sunucumdan bir dosya istendiğinde, yanıtla birlikte "Bu dosyanın kimliği şu" (ETag) ve "Bu dosya en son şu tarihte değiştirildi" (Last-Modified) bilgilerini gönderecektim. Tarayıcı da bir sonraki isteğinde, önbelleğindeki bu bilgileri If-None-Match (ETag için) ve If-Modified-Since (Last-Modified için) header'ları ile sunucuya gönderecekti. Eğer dosya değişmemişse, sunucu sadece 304 Not Modified durum kodu dönecek ve dosyanın gövdesi (body) boş olacaktı. Böylece sadece birkaç byte'lık header trafiği oluşacak, dosyanın kendisi tekrar indirilmeyecekti.

Node.js (Express) backend'imde bunu nasıl yaptığıma bir bakalım. Express, static dosya servis ederken zaten bu header'ları otomatik ekliyor ama ben biraz daha özelleştirmek istedim.

JavaScript:
const express = require('express');
const path = require('path');
const fs = require('fs').promises;
const crypto = require('crypto');

const app = express();

// Özel bir middleware ile ETag oluşturuyoruz
app.use('/assets', async (req, res, next) => {
    const filePath = path.join(__dirname, 'public', req.path);

    try {
        const stats = await fs.stat(filePath);
        const fileContent = await fs.readFile(filePath);

        // Dosya içeriğinden hash bazlı bir ETag oluştur
        const etag = crypto.createHash('md5').update(fileContent).digest('hex');

        // Last-Modified header'ını UTC formatında ayarla
        const lastModified = stats.mtime.toUTCString();

        // Header'ları yanıta ekle
        res.set('ETag', etag);
        res.set('Last-Modified', lastModified);

        // Tarayıcıdan gelen koşullu istek header'larını kontrol et
        const clientETag = req.headers['if-none-match'];
        const clientLastModified = req.headers['if-modified-since'];

        if (clientETag === etag || clientLastModified === lastModified) {
            // Dosya değişmemiş, 304 döndür
            return res.status(304).end();
        }

        // Dosya değişmişse veya ilk defa isteniyorsa, normal akışa devam et
        next();
    } catch (err) {
        // Dosya bulunamadı vs.
        next(err);
    }
});

// Static dosyaları servis et (Artık middleware'imiz header'ları kontrol ediyor)
app.use('/assets', express.static(path.join(__dirname, 'public'), {
    // Express static'in kendi ETag'ini devre dışı bırak, bizim middleware'imiz işlesin
    etag: false,
    lastModified: false
}));

app.listen(3000, () => console.log('Sunucu 3000 portunda çalışıyor...'));

Yukarıdaki kodda, /assets yoluna gelen her istek için önce bir middleware çalışıyor. Bu middleware, dosyanın hash'inden bir ETag ve son değiştirilme tarihinden de Last-Modified header'ını oluşturup yanıta ekliyor. Ardından, gelen istekte bu değerlerin olup olmadığını kontrol ediyor. Eşleşme varsa, hemen 304 Not Modified döndürüyor. Bu sayede, express.static middleware'ine gidip dosyayı tekrar okuma ve gönderme işi yapılmıyor.

✅ Sonuç ve Performans Kazanımı

Bu yapıyı kurduktan sonra, Chrome DevTools'un "Network" sekmesinde inanılmaz bir iyileşme gördüm. Örneğin, 150KB'lık bir `main.css` dosyam vardı. İlk yüklemede durum kodu 200 OK ve transfer edilen veri ~150KB idi. Sayfayı yenilediğimde ise durum kodu 304 Not Modified ve transfer edilen veri sadece 300 byte civarındaydı (sadece request/response header'ları). Bu, tek bir dosya için bile muazzam bir tasarruf. Onlarca dosya ve binlerce kullanıcı düşünüldüğünde, sunucu yükünde ve kullanıcı deneyiminde ciddi bir fark yaratıyor.

Siz backend taraflı (Laravel, Django, ASP.NET gibi) benzer bir cache stratejisi uyguladınız mı? Ya da CDN kullanıyorsanız, CDN provider'ınızın ETag ve Last-Modified header'larını yönetme şekli nasıl? Deneyimlerinizi yorumlarda paylaşırsanız çok sevinirim!
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri