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 |
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();
});
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.