İçeriğe geç
Performance

Web Image Optimization: Format, Boyut ve Lazy Loading

Tarık Tunç
Web Image Optimization: Format, Boyut ve Lazy Loading

Web Image Optimization: Format, Boyut ve Lazy Loading

Görseller, ortalama bir web sayfasının toplam boyutunun %50'sinden fazlasını oluşturur. HTTP Archive verilerine göre medyan bir web sayfası yaklaşık 1MB görsel içerik barındırır. Optimize edilmemiş görseller, LCP süresini uzatır, bant genişliğini tüketir ve mobil kullanıcılarda veri kotasını hızla eritir. Bu rehberde modern görsel optimizasyon tekniklerini, doğru format seçimini, responsive images stratejilerini ve lazy loading implementasyonunu detaylı olarak ele alacağız.

Görsel Format Karşılaştırması

Doğru format seçimi, dosya boyutunu dramatik şekilde azaltabilir:

Format Sıkıştırma Şeffaflık Animasyon Tarayıcı Desteği Kullanım Alanı
JPEG Kayıplı Hayır Hayır %100 Fotoğraflar
PNG Kayıpsız Evet Hayır %100 Grafikler, logolar
WebP Her ikisi Evet Evet %97+ Genel kullanım
AVIF Kayıplı Evet Evet %92+ Fotoğraflar, en iyi sıkıştırma
SVG Vektör Evet Evet %100 İkonlar, illüstrasyonlar
İpucu: AVIF, WebP'ye göre ortalama %20-30 daha küçük dosya boyutu sunar. Ancak encode süresi daha uzundur. Build-time optimizasyon yapıyorsanız AVIF'i birincil format olarak tercih edin.

Picture Elementi ile Format Fallback

Modern formatları desteklemeyen tarayıcılar için <picture> elementini kullanarak fallback sağlayabilirsiniz:

<!-- Progressive format fallback -->
<picture>
  <!-- AVIF: En iyi sıkıştırma -->
  <source
    type="image/avif"
    srcset="/images/hero-400.avif 400w,
            /images/hero-800.avif 800w,
            /images/hero-1200.avif 1200w"
    sizes="(max-width: 768px) 100vw, 50vw">

  <!-- WebP: Geniş destek, iyi sıkıştırma -->
  <source
    type="image/webp"
    srcset="/images/hero-400.webp 400w,
            /images/hero-800.webp 800w,
            /images/hero-1200.webp 1200w"
    sizes="(max-width: 768px) 100vw, 50vw">

  <!-- JPEG: Fallback -->
  <img
    src="/images/hero-800.jpg"
    srcset="/images/hero-400.jpg 400w,
            /images/hero-800.jpg 800w,
            /images/hero-1200.jpg 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    alt="Hero görseli açıklaması"
    width="1200" height="600"
    loading="lazy"
    decoding="async">
</picture>

Build-Time Görsel Optimizasyonu

Sharp kütüphanesi ile build aşamasında görselleri otomatik olarak optimize edebilirsiniz:

// optimize-images.js
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');

async function optimizeImage(inputPath, outputDir) {
  const filename = path.parse(inputPath).name;
  const sizes = [400, 800, 1200, 1600];

  for (const width of sizes) {
    const image = sharp(inputPath);
    const metadata = await image.metadata();

    // Orijinalden büyük boyut üretme
    if (width > metadata.width) continue;

    // WebP formatı
    await sharp(inputPath)
      .resize(width)
      .webp({ quality: 80, effort: 6 })
      .toFile(path.join(outputDir, `${filename}-${width}.webp`));

    // AVIF formatı
    await sharp(inputPath)
      .resize(width)
      .avif({ quality: 65, effort: 6 })
      .toFile(path.join(outputDir, `${filename}-${width}.avif`));

    // JPEG fallback
    await sharp(inputPath)
      .resize(width)
      .jpeg({ quality: 80, progressive: true, mozjpeg: true })
      .toFile(path.join(outputDir, `${filename}-${width}.jpg`));
  }

  console.log(`Optimized: ${filename}`);
}

// Klasördeki tüm görselleri işle
async function processDirectory(inputDir, outputDir) {
  const files = fs.readdirSync(inputDir)
    .filter(f => /\.(jpg|jpeg|png)$/i.test(f));

  for (const file of files) {
    await optimizeImage(
      path.join(inputDir, file),
      outputDir
    );
  }
}

processDirectory('./src/images', './public/images/optimized');

Lazy Loading Stratejileri

Viewport dışındaki görselleri gecikmeli yüklemek, ilk sayfa yükleme süresini önemli ölçüde azaltır:

<!-- Native lazy loading - en basit yöntem -->
<img src="/images/photo.webp"
     alt="Fotoğraf açıklaması"
     loading="lazy"
     decoding="async"
     width="800" height="600">

<!-- LCP öğesi: lazy loading KULLANMA -->
<img src="/images/hero.webp"
     alt="Hero görseli"
     fetchpriority="high"
     decoding="async"
     width="1200" height="600">

Daha fazla kontrol için Intersection Observer API kullanılabilir:

// Gelişmiş lazy loading with blur-up efekti
class LazyImageLoader {
  constructor() {
    this.observer = new IntersectionObserver(
      this.handleIntersect.bind(this),
      {
        rootMargin: '200px 0px',  // 200px öncesinden yüklemeye başla
        threshold: 0.01
      }
    );

    document.querySelectorAll('img[data-src]').forEach(img => {
      this.observer.observe(img);
    });
  }

  handleIntersect(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        this.loadImage(entry.target);
        this.observer.unobserve(entry.target);
      }
    });
  }

  loadImage(img) {
    const src = img.dataset.src;
    const srcset = img.dataset.srcset;

    // Yeni görsel önceden yükle
    const tempImg = new Image();
    tempImg.onload = () => {
      img.src = src;
      if (srcset) img.srcset = srcset;
      img.classList.add('loaded');
      img.removeAttribute('data-src');
    };
    tempImg.src = src;
  }
}

// Sayfa yüklendiğinde başlat
document.addEventListener('DOMContentLoaded', () => {
  new LazyImageLoader();
});
Uyarı: Above-the-fold (ekranın üst kısmında görünen) görsellere asla loading="lazy" eklemeyin. Bu, LCP metriğinizi ciddi şekilde kötüleştirir. Lazy loading yalnızca viewport altında kalan görseller için kullanılmalıdır.

Responsive Images Best Practices

srcset ve sizes attribute'ları ile tarayıcının en uygun boyuttaki görseli seçmesini sağlayın:

  • sizes attribute'u doğru tanımlayın: Görselin layout'taki gerçek boyutunu yansıtmalıdır
  • Gereksiz boyut varyasyonu üretmeyin: 3-5 breakpoint yeterlidir
  • Art direction için picture elementi kullanın: Farklı ekran boyutlarında farklı kırpım gerektiğinde
  • width ve height attribute'larını her zaman ekleyin: CLS önleme için zorunludur

CDN ve Otomatik Optimizasyon

Cloudinary, imgix veya Cloudflare Images gibi CDN servisleri, görselleri talep anında optimize edebilir. URL parametreleri ile format, boyut ve kalite kontrolü sağlanır. Bu yaklaşım build-time optimizasyona göre daha esnek olsa da, ek maliyet ve bağımlılık getirir.

Sonuç

Görsel optimizasyonu, web performansını iyileştirmenin en etkili yollarından biridir. Modern formatlar (WebP, AVIF), responsive images, lazy loading ve build-time optimizasyon birlikte kullanıldığında sayfa boyutunu %60-80 oranında azaltabilirsiniz. Her görselin amacına uygun format ve boyutta sunulması, hem kullanıcı deneyimini hem de bant genişliği maliyetlerini optimize eder.

Kaynaklar

İlgili Yazılar