Site hızı artık bir tercih değil, zorunluluk. Google'ın sıralama algoritmalarında Core Web Vitals doğrudan etkili, kullanıcıların %53'ü 3 saniyeden uzun yüklenen siteleri terk ediyor ve her 1 saniyelik gecikme dönüşüm oranını %7 düşürüyor. Bu yazıda web sitenizi hızlandırmak için uygulamanız gereken tüm teknikleri, araçlarla birlikte ele alıyoruz.
Core Web Vitals: Google'ın Hız Metrikleri
Google, 2021'den beri Core Web Vitals'ı sıralama faktörü olarak kullanıyor. 2026'da hedef değerler:
LCP (Largest Contentful Paint)
Sayfanın en büyük içerik elementinin render süresi.
- İyi: < 2.5 saniye
- İyileştirmeli: 2.5 - 4 saniye
- Kötü: > 4 saniye
INP (Interaction to Next Paint)
Kullanıcı etkileşimlerinin yanıt süresi (FID'nin yerini aldı).
- İyi: < 200ms
- İyileştirmeli: 200 - 500ms
- Kötü: > 500ms
CLS (Cumulative Layout Shift)
Sayfa yüklenirken içeriğin beklenmedik şekilde kayma miktarı.
- İyi: < 0.1
- İyileştirmeli: 0.1 - 0.25
- Kötü: > 0.25
1. Görsel Optimizasyon
Görseller, tipik bir web sayfasının toplam boyutunun %50-70'ini oluşturur. Görsel optimizasyon, en büyük hız kazanımını sağlar.
Modern Format Kullanımı
<!-- picture elementi ile format fallback -->
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero görsel" width="1200" height="630" />
</picture>
| Format | Boyut (1200x630 görsel) | Kalite | Tarayıcı Desteği |
|---|---|---|---|
| JPEG | 180 KB | Referans | %100 |
| WebP | 95 KB (%47 küçük) | Eşdeğer | %97 |
| AVIF | 55 KB (%69 küçük) | Eşdeğer | %92 |
Next.js Image Optimization
import Image from "next/image";
// Next.js otomatik olarak:
// - WebP/AVIF formatına dönüştürür
// - Responsive srcset oluşturur
// - Lazy loading uygular
// - Boyut placeholder gösterir (blur)
function HeroSection() {
return (
<Image
src="/hero.jpg"
alt="Maviona dijital ajans - modern web çözümleri"
width={1200}
height={630}
priority // Above-the-fold görseller için
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQ..."
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
/>
);
}
Görsel Boyutlandırma Kuralları
- Hero görseller: Max 1920px genişlik, 150 KB altı
- Blog görselleri: Max 1200px genişlik, 100 KB altı
- Thumbnail'ler: Max 400px genişlik, 30 KB altı
- İkonlar: SVG kullanın, PNG/JPG değil
- Arka plan desenleri: CSS gradients veya küçük tiling SVG
2. Lazy Loading
Görseller için Lazy Loading
<!-- Native lazy loading — modern tarayıcılarda yerleşik -->
<img src="product.jpg" alt="Ürün" loading="lazy" width="400" height="300" />
Önemli: Above-the-fold (ilk ekranda görünen) görsellere loading="lazy" eklemeyin. Bu, LCP'yi olumsuz etkiler. İlk ekrandaki görsellere loading="eager" veya Next.js'te priority kullanın.
Component Lazy Loading
import dynamic from "next/dynamic";
// Ağır component'leri lazy load edin
const HeavyChart = dynamic(() => import("./HeavyChart"), {
loading: () => <div className="h-96 animate-pulse bg-gray-100 rounded" />,
ssr: false, // Sadece istemcide yükle
});
const VideoPlayer = dynamic(() => import("./VideoPlayer"), {
loading: () => <div className="aspect-video bg-gray-900 rounded" />,
});
// Kullanım
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<HeavyChart data={chartData} />
<VideoPlayer url={videoUrl} />
</div>
);
}
Intersection Observer ile Lazy Loading
"use client";
import { useRef, useEffect, useState, ReactNode } from "react";
function LazySection({ children }: { children: ReactNode }) {
const ref = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.disconnect();
}
},
{ rootMargin: "200px" } // 200px önceden yükle
);
if (ref.current) observer.observe(ref.current);
return () => observer.disconnect();
}, []);
return (
<div ref={ref}>
{isVisible ? children : <div className="h-96" />}
</div>
);
}
3. Code Splitting
Route-Based Splitting (Otomatik)
Next.js'te her sayfa otomatik olarak ayrı bir chunk'a bölünür. /blog sayfası yüklenirken /hizmetler sayfasının JavaScript'i indirilmez.
Component-Based Splitting
// Koşullu yükleme — sadece gerektiğinde
import dynamic from "next/dynamic";
const AdminPanel = dynamic(() => import("./AdminPanel"));
const ChatWidget = dynamic(() => import("./ChatWidget"));
const CookieBanner = dynamic(() => import("./CookieBanner"));
function App({ user }) {
return (
<main>
<Header />
<Content />
{user?.isAdmin && <AdminPanel />}
{showChat && <ChatWidget />}
<CookieBanner />
</main>
);
}
Bundle Analizi
# Next.js bundle analyzer
npm install @next/bundle-analyzer
# next.config.ts
import bundleAnalyzer from "@next/bundle-analyzer";
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === "true",
});
export default withBundleAnalyzer(nextConfig);
# Analiz çalıştır
ANALYZE=true npm run build
Bundle analyzer ile hangi kütüphanelerin ne kadar yer kapladığını görün. Sık karşılaşılan sorunlar:
- moment.js (300 KB) → date-fns (30 KB) veya dayjs (7 KB)
- lodash (70 KB) → lodash-es (tree-shakeable) veya native methods
- chart.js (200 KB) → Lazy load yapın, sayfa yüklenirken yüklemeyin
4. Font Optimizasyonu
// Next.js font optimizasyonu — otomatik self-hosting
import { Inter, Poppins } from "next/font/google";
const inter = Inter({
subsets: ["latin", "latin-ext"],
display: "swap", // FOUT > FOIT
variable: "--font-inter",
});
const poppins = Poppins({
weight: ["400", "600", "700"],
subsets: ["latin", "latin-ext"],
display: "swap",
variable: "--font-poppins",
});
// Layout'ta kullan
export default function RootLayout({ children }) {
return (
<html className={`${inter.variable} ${poppins.variable}`}>
<body>{children}</body>
</html>
);
}
Font optimizasyon kuralları:
- Font sayısını sınırlayın: Max 2-3 font ailesi
- Ağırlık sayısını sınırlayın: Sadece kullandıklarınızı yükleyin
- display: swap kullanın: Font yüklenene kadar fallback font gösterin
- Subset kullanın: Türkçe için
latin-extyeterli, tüm Unicode'u yüklemeyin - Self-host edin: Google Fonts CDN yerine kendi sunucunuzdan sunun (Next.js bunu otomatik yapar)
5. CDN ve Caching Stratejileri
HTTP Cache Headers
// Next.js API route veya middleware'de
export function middleware(request: NextRequest) {
const response = NextResponse.next();
// Statik dosyalar — uzun süreli cache
if (request.nextUrl.pathname.match(/\.(js|css|woff2|png|jpg|svg)$/)) {
response.headers.set(
"Cache-Control",
"public, max-age=31536000, immutable"
);
}
// HTML sayfalar — kısa cache + revalidation
if (request.nextUrl.pathname.match(/^\/(?!api)/)) {
response.headers.set(
"Cache-Control",
"public, max-age=0, s-maxage=3600, stale-while-revalidate=86400"
);
}
return response;
}
Cache stratejisi özeti
| İçerik Türü | Cache Süresi | Strateji |
|---|---|---|
| JS/CSS (hashed) | 1 yıl | immutable |
| Görseller | 1 yıl | immutable (fingerprinted) |
| Fontlar | 1 yıl | immutable |
| HTML sayfalar | 0 (s-maxage: 1 saat) | stale-while-revalidate |
| API yanıtları | 0-5 dakika | Veriye göre değişir |
6. JavaScript Optimizasyonu
Third-Party Script Yönetimi
import Script from "next/script";
function Layout({ children }) {
return (
<>
{children}
{/* Analytics — sayfa yüklendikten sonra */}
<Script
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"
strategy="afterInteractive"
/>
{/* Chat widget — kullanıcı idle olduğunda */}
<Script
src="https://widget.intercom.io/widget/xxxxx"
strategy="lazyOnload"
/>
</>
);
}
7. Ölçüm Araçları
Geliştirme Aşamasında
- Chrome DevTools Lighthouse: Yerel performans testi
- Chrome DevTools Performance paneli: CPU profiling, long tasks tespit
- Chrome DevTools Network paneli: Waterfall analizi, büyük dosya tespiti
Production'da
- Google PageSpeed Insights: Lab + Field verisi
- Chrome UX Report (CrUX): Gerçek kullanıcı metrikleri
- Google Search Console — Core Web Vitals raporu: Sayfa gruplarının performansı
- web.dev/measure: Detaylı performans raporu
Kontrol Listesi
Hız optimizasyonu yaparken bu sırayı izleyin:
- Mevcut durumu ölçün (Lighthouse + CrUX)
- En büyük sorunları tespit edin (genellikle görseller ve üçüncü parti scriptler)
- Görselleri optimize edin (format + boyut + lazy loading)
- Üçüncü parti scriptleri erteleyin
- Font yükleme stratejisini optimize edin
- Code splitting uygulayın
- Cache stratejisini kurun
- CDN kullanın
- Tekrar ölçün ve karşılaştırın
- Düzenli monitoring kurun
Sonuç
Web sitesi hızı, kullanıcı deneyimi, SEO ve dönüşüm oranları açısından kritik. İyi haber şu ki, modern araçlar ve framework'ler (Next.js, Cloudflare Pages) performans optimizasyonunun büyük bölümünü otomatikleştiriyor. Siz de doğru stratejileri uygulayarak sitenizi saniyeler içinde yüklenen, Google'ın sevdiği ve kullanıcıların terk etmediği bir deneyime dönüştürebilirsiniz.
Sitenizin hız performansını analiz ettirmek ve optimize etmek istiyorsanız, Maviona'dan ücretsiz performans analizi talep edin.
