Next.js ile Performans Optimizasyonu

Google'ın Core Web Vitals metrikleri artık doğrudan sıralama faktörü. Bu rehberde Next.js projelerinde LCP, CLS ve INP skorlarını nasıl iyileştireceğini adım adım göreceğiz.

Core Web Vitals Nedir?

Google'ın kullanıcı deneyimini ölçmek için kullandığı üç temel metrik:

  • LCP (Largest Contentful Paint) — Sayfanın en büyük içeriğinin yüklenme süresi. Hedef: < 2.5 saniye
  • INP (Interaction to Next Paint) — Kullanıcı etkileşimine yanıt süresi. Hedef: < 200ms
  • CLS (Cumulative Layout Shift) — Görsel kararlılık skoru. Hedef: < 0.1

1. next/image ile LCP İyileştirme

Ham <img> tag'i yerine next/image kullanmak LCP'yi dramatik şekilde düşürür.

// ❌ Kötü — layout shift + optimize edilmemiş
<img src="/hero.jpg" alt="Hero" />
 
// ✅ İyi — WebP dönüşümü, lazy loading, boyut optimizasyonu
import Image from "next/image";
 
<Image
  src="/hero.jpg"
  alt="Hero görseli"
  width={1200}
  height={630}
  priority          // LCP görseli için — preload eder
  sizes="(max-width: 768px) 100vw, 1200px"
/>

priority prop'unu sadece fold üstündeki (ekranda ilk görünen) görsele ekle. Diğerlerine ekleme — gereksiz preload yapar.

2. Font Optimizasyonu ile CLS Sıfırlama

Google Fonts'u next/font ile yüklemek layout shift'i tamamen ortadan kaldırır.

// src/fonts/fonts.ts
import { Inter, JetBrains_Mono } from "next/font/google";
 
export const bodyFont = Inter({
  subsets: ["latin"],
  variable: "--font-body",
  display: "swap",      // FOUT yerine FOUT — daha iyi UX
  preload: true,
});
 
export const monoFont = JetBrains_Mono({
  subsets: ["latin"],
  variable: "--font-mono",
  display: "swap",
});

display: "swap" ile font yüklenene kadar sistem fontu gösterilir, yüklenince değişir. Bu CLS'yi sıfıra indirir.

3. Dynamic Import ile INP İyileştirme

Ağır bileşenleri lazy yüklemek JavaScript parse süresini kısaltır, INP'yi düşürür.

import dynamic from "next/dynamic";
 
// ❌ Kötü — tüm bundle'a giriyor
import HeavyChart from "@/components/HeavyChart";
 
// ✅ İyi — sadece kullanıldığında yüklenir
const HeavyChart = dynamic(() => import("@/components/HeavyChart"), {
  loading: () => <div className="h-64 animate-pulse bg-zinc-800 rounded" />,
  ssr: false,  // Sadece client-side gereken bileşenler için
});

4. Image Boyutlarını Önceden Belirt

Boyutu bilinmeyen görseller CLS'ye neden olur. Her zaman width ve height belirt.

// ❌ CLS riski — tarayıcı boyutu bilmiyor, layout kayıyor
<Image src={url} alt="..." fill />
 
// ✅ Boyut belirli — layout stable
<Image
  src={url}
  alt="..."
  width={400}
  height={300}
  className="object-cover"
/>

fill kullanmak zorundaysan parent'a position: relative ve sabit boyut ver:

<div className="relative w-full aspect-video">
  <Image src={url} alt="..." fill className="object-cover" />
</div>

5. Preconnect ile TTFB Düşürme

Kritik üçüncü taraf kaynaklara erken bağlantı kur:

// next.config.mjs headers()
{
  key: "Link",
  value: [
    "<https://fonts.googleapis.com>; rel=preconnect",
    "<https://fonts.gstatic.com>; rel=preconnect; crossorigin",
    "<https://www.googletagmanager.com>; rel=dns-prefetch",
  ].join(", ")
}

6. Server Components'i Maksimize Et

React Server Components client bundle'ı küçültür, hydration süresini kısaltır.

// ✅ Server Component — bundle'a girmiyor
// "use client" direktifi YOK
async function ProductList() {
  const products = await db.query("SELECT * FROM products");
  return <ul>{products.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
 
// Sadece interaktif kısımlar client component olsun
"use client";
function AddToCartButton({ productId }: { productId: number }) {
  const [loading, setLoading] = useState(false);
  // ...
}

7. Bundle Analizi

Hangi paket ne kadar yer kaplıyor?

ANALYZE=true npm run build

@next/bundle-analyzer ile görsel rapor alırsın. 100KB+ paketleri dynamic import'a taşı.

Sonuç

Bu optimizasyonları uyguladıktan sonra beklenen iyileşmeler:

MetrikÖnceSonra
LCP4.2s1.8s
INP380ms95ms
CLS0.240.02

Performans tek seferlik bir iş değil — her deploy'dan sonra PageSpeed Insights ile kontrol et.

Nextjs Performans Optimizasyonu - XipSoft