İçeriğe geç
nextjs

Next.js Image Optimizasyonu: next/image Rehberi

Tarık Tunç
Next.js Image Optimizasyonu: next/image Rehberi

Next.js Image Optimizasyonu: next/image Rehberi

Görseller, web sayfalarının en ağır bileşenleridir ve optimize edilmediğinde sayfa performansını ciddi şekilde etkiler. Next.js'in next/image bileşeni, otomatik boyutlandırma, lazy loading, format dönüşümü ve responsive tasarım gibi optimizasyonları yerleşik olarak sunar. Bu rehberde next/image'ın tüm özelliklerini ve en iyi kullanım pratiklerini inceleyeceğiz.

Temel Kullanım

next/image bileşeni, standart HTML <img> etiketinin gelişmiş bir versiyonudur:

import Image from 'next/image';

export default function Hero() {
  return (
    <div className="relative h-[500px]">
      <Image
        src="/images/hero-banner.jpg"
        alt="Ana sayfa banner görseli"
        fill
        priority
        className="object-cover"
      />
    </div>
  );
}

Lokal ve Remote Görseller

import Image from 'next/image';
import profilePic from '@/public/images/profile.jpg'; // Statik import

export default function Profile() {
  return (
    <div>
      {/* Statik import — boyutlar otomatik belirlenir */}
      <Image
        src={profilePic}
        alt="Profil fotoğrafı"
        placeholder="blur" // Statik import'ta otomatik blur
      />

      {/* Remote görsel — boyut belirtmek zorunlu */}
      <Image
        src="https://example.com/photo.jpg"
        alt="Remote görsel"
        width={800}
        height={600}
      />
    </div>
  );
}

Remote Pattern Konfigürasyonu

Remote görselleri kullanmak için next.config.js'te izin verilen domain'leri tanımlayın:

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.unsplash.com',
      },
      {
        protocol: 'https',
        hostname: '*.amazonaws.com',
      },
      {
        protocol: 'https',
        hostname: 'cdn.example.com',
        pathname: '/images/**',
      },
    ],
  },
};

module.exports = nextConfig;
Uyarı: Remote görselleri tanımlarken wildcard (*) kullanımına dikkat edin. Güvenlik için mümkün olduğunca spesifik pattern'ler tanımlayın.

Fill Mode ve Responsive Görseller

import Image from 'next/image';

// Fill mode — parent container'ı doldurur
export function HeroImage() {
  return (
    <div className="relative w-full h-[400px]">
      <Image
        src="/images/hero.jpg"
        alt="Hero"
        fill
        sizes="100vw"
        className="object-cover rounded-lg"
        priority
      />
    </div>
  );
}

// Responsive grid görselleri
export function ImageGrid({ images }: { images: ImageType[] }) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
      {images.map((img) => (
        <div key={img.id} className="relative aspect-video">
          <Image
            src={img.url}
            alt={img.alt}
            fill
            sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
            className="object-cover rounded-lg"
          />
        </div>
      ))}
    </div>
  );
}
İpucu: sizes prop'u, tarayıcıya hangi genişlikte hangi boyutta görsel kullanacağını söyler. Doğru sizes değeri, gereksiz büyük görsellerin indirilmesini önler.

Priority ve Lazy Loading

import Image from 'next/image';

export default function Page() {
  return (
    <>
      {/* LCP görseli — priority ile preload edilir */}
      <Image
        src="/images/above-fold.jpg"
        alt="Ana görsel"
        width={1200}
        height={600}
        priority // Lazy loading devre dışı, preload eklenir
      />

      {/* Sayfa aşağısındaki görseller — varsayılan lazy loading */}
      <Image
        src="/images/below-fold.jpg"
        alt="Alt görsel"
        width={800}
        height={400}
        loading="lazy" // Varsayılan
      />
    </>
  );
}

Placeholder ve Blur Effect

import Image from 'next/image';

// Statik import ile otomatik blur
import heroImage from '@/public/hero.jpg';

export function BlurExample() {
  return (
    <Image
      src={heroImage}
      alt="Blur placeholder örneği"
      placeholder="blur" // Otomatik blur data URL oluşturulur
    />
  );
}

// Remote görsel için manuel blurDataURL
export function RemoteBlurExample() {
  return (
    <Image
      src="https://example.com/photo.jpg"
      alt="Remote blur"
      width={800}
      height={600}
      placeholder="blur"
      blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
    />
  );
}

// Renk placeholder
export function ColorPlaceholder() {
  return (
    <div className="relative aspect-video bg-gray-200">
      <Image
        src="/images/photo.jpg"
        alt="Renk placeholder"
        fill
        placeholder="empty" // Varsayılan — placeholder yok
      />
    </div>
  );
}

Image Konfigürasyonu

// next.config.js
const nextConfig = {
  images: {
    // Desteklenen formatlar
    formats: ['image/avif', 'image/webp'],

    // Üretilecek boyutlar
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],

    // Cache süresi (saniye)
    minimumCacheTTL: 60 * 60 * 24 * 30, // 30 gün

    // Harici loader (Cloudinary, Imgix vb.)
    // loader: 'custom',
    // loaderFile: './lib/image-loader.ts',

    // Optimizasyonu devre dışı bırak (önerilmez)
    // unoptimized: true,
  },
};

Custom Image Loader

// lib/image-loader.ts
export default function cloudinaryLoader({
  src,
  width,
  quality,
}: {
  src: string;
  width: number;
  quality?: number;
}) {
  const params = [
    `f_auto`,
    `c_limit`,
    `w_${width}`,
    `q_${quality || 'auto'}`,
  ];
  return `https://res.cloudinary.com/demo/image/upload/${params.join(',')}${src}`;
}

// Kullanım
import Image from 'next/image';

<Image
  loader={cloudinaryLoader}
  src="/my-image.jpg"
  alt="Cloudinary görsel"
  width={800}
  height={600}
/>
Bilgi: Next.js, görselleri varsayılan olarak WebP veya AVIF formatına dönüştürür. Bu formatlar JPEG'e göre %25-50 daha küçüktür ve görsel kaliteyi korur.

Performans İpuçları

  • Above-the-fold görsellere priority ekleyin
  • Her zaman alt text kullanın (erişilebilirlik ve SEO)
  • sizes prop'unu doğru ayarlayın
  • Statik görseller için import kullanarak otomatik blur placeholder alın
  • Dekoratif görsellerde alt="" kullanın
  • Büyük görselleri fill mode ile responsive yapın

Sonuç

Next.js next/image bileşeni, görsel optimizasyonunu otomatikleştirerek Core Web Vitals skorlarını önemli ölçüde iyileştirir. Lazy loading, format dönüşümü, responsive boyutlandırma ve cache mekanizması gibi özelliklerle minimum çabayla maksimum performans elde edersiniz. Priority ve sizes prop'larını doğru kullanmak, LCP metriğinizi doğrudan etkiler.

Kaynaklar

İlgili Yazılar