Skip to content

Web Performance Rehberi

📌 Ne Zaman Kullanılır?

  • ✅ Her web projesi — performans SEO ve kullanıcı deneyimi için kritik
  • ⚠️ Premature optimization'dan kaçının — önce ölçün, sonra optimize edin
  • ❌ —

Önerilen Kullanım: Production öncesi performans audit + sürekli monitoring Araçlar: Lighthouse, PageSpeed Insights, WebPageTest, Chrome DevTools


1) Core Web Vitals

Google'un web deneyimini olcmek için belirledigi uc temel metrik. Arama siralamasini dogrudan etkiler.

LCP — Largest Contentful Paint

Sayfadaki en büyük gorsel veya metin blogunun render süresi. <img>, <video> poster, CSS background-image ve büyük metin bloklari LCP element olabilir.

Iyilestirme: Hero image'i preload et, TTFB'yi dusur (< 800ms), render-blocking kaynaklari azalt, gorselleri optimize et (WebP/AVIF).

html
<link rel="preload" as="image" href="/hero.webp" type="image/webp">

FID / INP — First Input Delay / Interaction to Next Paint

FID (eski): Ilk etkilesimden tarayici yanitina kadar gecen sure. INP (yeni, Mart 2024): Tüm etkilesimlerin yanit suresini olcer, en kotu etkilesimi baz alir.

Iyilestirme: Uzun main thread gorevlerini parcala, heavy computation'lari Web Worker'a tasi, gereksiz JS'i lazy load et.

javascript
// Uzun gorevleri parcalama
async function processLargeList(items) {
  for (let i = 0; i < items.length; i++) {
    processItem(items[i]);
    if (i % 5 === 0) await new Promise(r => setTimeout(r, 0)); // yield
  }
}

CLS — Cumulative Layout Shift

İçerik kaymasini olcer. Gorsellere width/height belirtin, reklam alanlarina sabit boyut verin, font-display: optional kullanin.

html
<img src="photo.webp" width="800" height="600" alt="Aciklama">
<style>.hero { aspect-ratio: 16 / 9; width: 100%; }</style>

Hedef Degerler Tablosu

MetrikGoodNeeds ImprovementPoor
LCP< 2.5s2.5s - 4.0s> 4.0s
INP< 200ms200ms - 500ms> 500ms
CLS< 0.10.1 - 0.25> 0.25
FID (eski)< 100ms100ms - 300ms> 300ms
TTFB< 800ms800ms - 1800ms> 1800ms
FCP< 1.8s1.8s - 3.0s> 3.0s

Olcum:

javascript
import { onLCP, onINP, onCLS } from 'web-vitals';

onLCP(m => sendToAnalytics({ name: 'LCP', value: m.value, id: m.id }));
onINP(m => sendToAnalytics({ name: 'INP', value: m.value, id: m.id }));
onCLS(m => sendToAnalytics({ name: 'CLS', value: m.value, id: m.id }));

2) Lighthouse

Google'un performans audit araci. Performance, Accessibility, Best Practices, SEO kategorilerinde analiz yapar.

Chrome DevTools ile

F12 > Lighthouse sekmesi > Kategorileri seç > "Analyze page load". Incognito modda calistirin — extension'lar sonuclari etkiler.

CLI Kullanimi

bash
npm install -g lighthouse
lighthouse https://example.com --output html --output-path ./report.html
lighthouse https://example.com --only-categories=performance
lighthouse https://example.com --preset=desktop   # Desktop modu

CI Entegrasyonu — Lighthouse CI

bash
npm install --save-dev @lhci/cli
javascript
// lighthouserc.js
module.exports = {
  ci: {
    collect: {
      url: ['http://localhost:3000'],
      startServerCommand: 'npm run start',
      numberOfRuns: 3,
    },
    assert: {
      assertions: {
        'categories:performance': ['error', { minScore: 0.9 }],
        'categories:accessibility': ['warn', { minScore: 0.9 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
      },
    },
    upload: { target: 'temporary-public-storage' },
  },
};
yaml
# .github/workflows/lighthouse.yml
name: Lighthouse CI
on: [push, pull_request]
jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci && npm run build
      - run: npx @lhci/cli autorun

Skor Kategorileri

KategoriAçıklamaHedef
PerformanceSayfa hizi, yuklenme sureleri90+
AccessibilityErisebilirlik90+
Best PracticesModern standartlara uyum90+
SEOArama motoru optimizasyonu90+

Skor renkleri: 0-49 kirmizi, 50-89 turuncu, 90-100 yesil.


3) Image Optimization

Gorseller genellikle toplam sayfa boyutunun %50+'sini olusturur.

Format Karşılaştırma

FormatBoyutKaliteSeffaflikBrowser Support
JPEGOrtaIyi (lossy)HayirTüm tarayicilar
PNGBüyükMükemmel (lossless)EvetTüm tarayicilar
WebPKüçük (%25-35 JPEG'den)Cok iyiEvet%97+
AVIFEn küçük (%50 JPEG'den)En iyiEvet%92+
SVGDeğişken (vektor)Sinirsiz ölçekEvetTüm tarayicilar

Strateji: Fotograflar: AVIF > WebP > JPEG. Ikonlar/logolar: SVG.

Lazy Loading ve Responsive Images

html
<!-- picture ile format fallback -->
<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="Hero" width="1200" height="800">
</picture>

<!-- Lazy loading — above-the-fold haric tum gorsellere -->
<img src="photo.webp" alt="..." loading="lazy" width="400" height="300">

<!-- LCP element — eager + high priority -->
<img src="hero.webp" alt="Hero" loading="eager" fetchpriority="high">

<!-- Responsive images — srcset + sizes -->
<img
  srcset="photo-400w.webp 400w, photo-800w.webp 800w, photo-1200w.webp 1200w"
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
  src="photo-800w.webp" alt="..." loading="lazy"
>

Next.js — next/image

tsx
import Image from 'next/image';
import heroImg from '@/public/hero.jpg';

// Statik import — otomatik boyut + blur placeholder
<Image src={heroImg} alt="Hero" priority placeholder="blur" />

// Remote image — boyut zorunlu
<Image src="https://example.com/photo.jpg" alt="..." width={800} height={600}
  quality={80} sizes="(max-width: 768px) 100vw, 50vw" />

// Fill modu — parent'i doldurur
<div style={{ position: 'relative', height: 400 }}>
  <Image src="/bg.jpg" alt="..." fill style={{ objectFit: 'cover' }} />
</div>

Nuxt Image

vue
<NuxtImg src="/hero.jpg" width="800" height="600" format="webp" quality="80" loading="lazy" />
<NuxtPicture src="/hero.jpg" format="avif,webp" width="1200" height="800" />

Sharp ile Server-Side Optimize

javascript
const sharp = require('sharp');

await sharp('input.jpg').resize(800, 600, { fit: 'cover' }).webp({ quality: 80 }).toFile('output.webp');
await sharp('input.jpg').resize(1200).avif({ quality: 50 }).toFile('output.avif');

// Birden fazla boyut
for (const size of [400, 800, 1200, 1600]) {
  await sharp('input.jpg').resize(size).webp({ quality: 80 }).toFile(`output-${size}w.webp`);
}

4) Font Optimization

Web fontlari render'i geciktirebilir. Doğru strateji ile metin hemen gorunur, layout shift onlenir.

font-display

DegerDavranisKullanım
swapFallback göster, font yuklenince değiştirEn yaygin, FOIT'i onler
optionalFallback göster, font yuklenmediyse kalirCLS'i tamamen onler
fallback100ms bekle, 3s icinde yuklenmezse fallback kalirOrta yol
block3s gorunmez bekleSadece ikon fontlari

FOUT vs FOIT

  • FOUT (Flash of Unstyled Text): Metin fallback ile gorunur, sonra degisir. Çözüm: font-display: optional
  • FOIT (Flash of Invisible Text): Metin gorunmez bekler. Çözüm: font-display: swap

Font Subset ve Preload

css
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap;
  unicode-range: U+0000-00FF, U+011E-011F, U+0130-0131, U+015E-015F; /* Latin + Turkce */
}
html
<link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin>
bash
# pyftsubset ile subset olusturma
pyftsubset "Font.ttf" --output-file="Font-subset.woff2" --flavor=woff2 \
  --unicodes="U+0000-00FF,U+011E-011F,U+0130-0131,U+015E-015F"

Next.js — next/font

tsx
import { Inter } from 'next/font/google';
import localFont from 'next/font/local';

const inter = Inter({ subsets: ['latin', 'latin-ext'], display: 'swap', variable: '--font-inter' });
const custom = localFont({
  src: [
    { path: './fonts/Custom-Regular.woff2', weight: '400' },
    { path: './fonts/Custom-Bold.woff2', weight: '700' },
  ],
  display: 'swap',
});

// layout.tsx
<html className={inter.variable}><body className={inter.className}>{children}</body></html>

Variable Fonts

Tek dosyada tüm agirliklar (100-900). Daha az HTTP istegi, daha küçük toplam boyut.

css
@font-face {
  font-family: 'InterVariable';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-display: swap;
  font-weight: 100 900;
}

Self-Hosting vs CDN

KriterSelf-HostingCDN (Google Fonts)
PerformansDaha iyi (ayni origin)Ek DNS + bağlantı
GizlilikGDPR uyumluIP Google'a gider
KontrolTam (subset, format)Sınırlı

Öneri: Self-hosting tercih edin. next/font veya Fontsource kullanin.


5) JavaScript Performance

JavaScript sayfanin en pahali kaynagi — parse, compile ve execute main thread'i bloklar.

Code Splitting

javascript
// Dynamic import — ihtiyac duyulunca yukle
const loadChart = async () => {
  const { Chart } = await import('./chart-library');
  Chart.render(data);
};
tsx
// React.lazy ile component splitting
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
const Settings = lazy(() => import('./Settings'));

<Suspense fallback={<Spinner />}>
  <Routes>
    <Route path="/dashboard" element={<Dashboard />} />
    <Route path="/settings" element={<Settings />} />
  </Routes>
</Suspense>

Next.js App Router'da her page.tsx otomatik ayri chunk olusturur.

Tree Shaking

javascript
// KOTU — tum kutuphane (~70KB)
import _ from 'lodash';

// IYI — sadece kullanilan fonksiyon (~2KB)
import get from 'lodash/get';

// DAHA IYI — ES module (tree-shakeable)
import { get } from 'lodash-es';

Gereksinimler: ES Modules kullanin, package.json'da "sideEffects": false ekleyin.

Bundle Analysis

javascript
// vite.config.js
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
  plugins: [visualizer({ open: true, gzipSize: true, brotliSize: true })],
});

// next.config.js — @next/bundle-analyzer
const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true' });
module.exports = withBundleAnalyzer({});
// ANALYZE=true npm run build

defer vs async

ÖzellikNormalasyncdefer
HTML parse'i bloklarEvetKismenHayir
Sira garantiliEvetHayirEvet
KullanımAnalytics, reklamlarUygulama kodu
html
<script defer src="app.js"></script>
<script async src="analytics.js"></script>

Third-Party Script — Partytown

Third-party script'leri Web Worker'a tasiyarak main thread'i serbest birakir.

html
<script type="text/partytown" src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>
tsx
// Next.js
<Script src="https://www.googletagmanager.com/gtag/js?id=GA_ID" strategy="worker" />

6) CSS Performance

Critical CSS

Above-the-fold CSS'i inline olarak HTML'e gomun, geri kalani asenkron yukleyin.

html
<head>
  <style>
    body { margin: 0; font-family: system-ui, sans-serif; }
    .header { background: #1a1a2e; color: white; padding: 1rem; }
    .hero { padding: 4rem 2rem; text-align: center; }
  </style>
  <link rel="preload" href="/styles/main.css" as="style"
    onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/styles/main.css"></noscript>
</head>

PurgeCSS / Tailwind Purge

Kullanilmayan CSS kurallarini kaldirir. Tailwind CSS v3+ otomatik purge yapar — sadece content doğru ayarlanmali.

javascript
// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
};

contain, will-change, content-visibility

css
/* contain — layout/paint hesaplamalarini izole eder */
.card { contain: layout style paint; }

/* will-change — SADECE animasyon oncesi, sonra kaldirin */
.card:hover { will-change: transform; }
/* * { will-change: transform; }  YAPMAYIN — bellek israfi */

/* content-visibility — gorunmeyen elementlerin render'ini erteler */
.list-item {
  content-visibility: auto;
  contain-intrinsic-size: auto 200px; /* scroll bar icin tahmini boyut */
}

content-visibility: auto uzun sayfalarda ilk render suresini %50+ azaltabilir.


7) Network Optimization

HTTP/2 Multiplexing

Tek TCP baglantisi uzerinden birden fazla istek ayni anda. Domain sharding ve sprite birlestirme artik gereksiz.

Compression — gzip vs Brotli

ÖzellikgzipBrotli
Sikistirma oraniIyi%15-25 daha iyi
HizHızlıYavas (statik için sorun degil)
Browser SupportTüm tarayicilar%97+ (HTTPS gerekli)
nginx
# Nginx
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript text/xml image/svg+xml;
gzip on;
gzip_comp_level 6;

CDN

CDNAvantajKullanım
CloudflareÜcretsiz plan, DDoS korumasiGenel amacli
Vercel EdgeNext.js entegrasyonuNext.js projeleri
AWS CloudFrontAWS ekosistemiAWS altyapisi

Resource Hints

HintNe YaparKullanım
preloadKesinlikle gereken kaynagi hemen indirFont, critical CSS, hero image
prefetchSonraki sayfa kaynagini bosta iken indirSonraki sayfa bundle'i
preconnectOnceden TCP+TLS baglantisi kurAPI sunucusu, CDN
dns-prefetchSadece DNS cozumle (hafif)Düşük oncelikli 3rd-party domain
html
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://analytics.example.com">
<link rel="prefetch" href="/about/page.js">

Fazla preload ters etki yapar. preconnect en fazla 4-6 domain için kullanin.


8) Caching

Cache-Control Header

# Hash'li statik asset'ler (JS, CSS, image)
Cache-Control: public, max-age=31536000, immutable

# HTML sayfalari
Cache-Control: public, max-age=0, must-revalidate

# API yanitlari
Cache-Control: private, max-age=60, stale-while-revalidate=300

# Hassas veri
Cache-Control: no-store
DirektifAnlam
publicCDN + tarayici cache'leyebilir
privateSadece tarayici (CDN hayir)
max-age=NN saniye cache'ten sun
s-maxage=NCDN için ayri max-age
stale-while-revalidate=NEski cache'i sun, arka planda yenile
immutableCache süresi boyunca sunucuya sorma
no-storeHicbir yerde cache'leme

ETag / Last-Modified

Sunucu ETag header'i gonderir. Sonraki isteklerde tarayici If-None-Match ile sorar. Degismediyse 304 Not Modified doner (body bos, bant genisligi tasarrufu).

Service Worker — Offline Cache

javascript
const CACHE_NAME = 'app-v1';
const ASSETS = ['/', '/index.html', '/styles/main.css', '/scripts/app.js'];

self.addEventListener('install', e => {
  e.waitUntil(caches.open(CACHE_NAME).then(c => c.addAll(ASSETS)));
});

self.addEventListener('fetch', e => {
  e.respondWith(
    caches.match(e.request).then(cached =>
      cached || fetch(e.request).then(res => {
        caches.open(CACHE_NAME).then(c => c.put(e.request, res.clone()));
        return res;
      })
    )
  );
});

Stratejiler: Cache-first (statik asset), Network-first (API), Stale-while-revalidate (feed).

Immutable Assets — Hash Filename

Build ciktisinda app.a1b2c3d4.js seklinde hash eklenir. İçerik degisince hash degisir, yeni dosya adi olusur. Boylece immutable guvenle kullanilir. Vite/Webpack bunu otomatik yapar.


9) Rendering Stratejileri

ÖzellikCSRSSRSSGISR
Render neredeTarayiciSunucu (her istek)Build timeBuild + periyodik
Ilk yüklemeYavas FCPHızlı FCPEn hızlıHızlı (cache)
SEOKotuMükemmelMükemmelMükemmel
Veri tazeligiGuncelGuncelBuild anindakiPeriyodik güncelleme
Sunucu yukuYokYüksekYokDüşük
KullanımDashboard, SPAE-ticaretBlog, docsHaber, katalog

Next.js örnekleri:

tsx
// SSG — build time'da statik olustur
export async function generateStaticParams() {
  const posts = await getPosts();
  return posts.map(post => ({ slug: post.slug }));
}

// SSR — her istekte taze veri
const data = await fetch('https://api.example.com/data', { cache: 'no-store' });

// ISR — belirli araliklarla yenile
const data = await fetch('https://api.example.com/products', { next: { revalidate: 3600 } });

10) React Performance

React.memo, useMemo, useCallback

tsx
import { memo, useMemo, useCallback, useState } from 'react';

const ExpensiveList = memo(function ExpensiveList({ items, onSelect }) {
  return <ul>{items.map(i => <li key={i.id} onClick={() => onSelect(i.id)}>{i.name}</li>)}</ul>;
});

function App() {
  const [count, setCount] = useState(0);
  const [items] = useState([{ id: 1, name: 'A' }, { id: 2, name: 'B' }]);

  const handleSelect = useCallback((id) => console.log(id), []);
  const sorted = useMemo(() => [...items].sort((a, b) => a.name.localeCompare(b.name)), [items]);

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
      <ExpensiveList items={sorted} onSelect={handleSelect} />
    </div>
  );
}

Ne zaman kullanilir:

DurumArac
Pahali hesaplama (sort, filter)useMemo
Child'a gecen callbackuseCallback
Sik render olan büyük listeReact.memo
Basit component, basit propsOptimizasyon gereksiz

Kural: Once React Profiler ile yavas component'leri tespit edin, sonra optimize edin.

Virtualization — react-window

tsx
import { FixedSizeList } from 'react-window';

// 10.000 satir — sadece gorunen ~20 satir render edilir
<FixedSizeList height={600} itemCount={items.length} itemSize={50} width="100%">
  {({ index, style }) => <div style={style}>{items[index].name}</div>}
</FixedSizeList>

Suspense ve Lazy Loading

tsx
const HeavyChart = lazy(() => import('./HeavyChart'));

<Suspense fallback={<div style={{ height: 400, background: '#e0e0e0' }} />}>
  <HeavyChart />
</Suspense>

React Profiler

Chrome DevTools > React DevTools > Profiler sekmesi > Record > Etkilesim > Stop > Flame chart'ta yavas component'leri bul. "Why did this render?" ile gereksiz render'lari tespit edin.

tsx
<Profiler id="MainContent" onRender={(id, phase, actualDuration) => {
  console.log(id, phase, actualDuration + 'ms');
}}>
  <MainContent />
</Profiler>

11) Database Query Performance

N+1 Problem

javascript
// KOTU — 1 + N sorgu
const posts = await Post.findAll();
for (const post of posts) {
  post.author = await User.findById(post.userId); // Her post icin ayri sorgu
}

// IYI — 2 sorgu (eager loading)
const posts = await Post.findAll({ include: [{ model: User, as: 'author' }] });

Indexing

sql
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_posts_user_date ON posts(user_id, created_at); -- composite

Detayli bilgi için veritabani rehberlerine bakiniz.


12) Monitoring

PageSpeed Insights

pagespeed.web.dev — Lab data (Lighthouse) + Field data (gercek kullanici, son 28 gun).

WebPageTest

webpagetest.org — Waterfall chart, film strip, farkli lokasyon/cihaz testi. Waterfall'da uzun mor cubuk = yavas sunucu (backend optimize edin), uzun mavi cubuk = büyük dosya (sikistirin).

Chrome DevTools Performance Tab

F12 > Performance > Record > Etkilesim > Stop. Flame chart'ta sari = JavaScript, mor = Layout, yesil = Paint. Experience satirindaki kirmizi ucgenler layout shift olaylarini gosterir.

Real User Monitoring (RUM)

javascript
window.addEventListener('load', () => {
  setTimeout(() => {
    const nav = performance.getEntriesByType('navigation')[0];
    const fcp = performance.getEntriesByType('paint')
      .find(p => p.name === 'first-contentful-paint')?.startTime;

    navigator.sendBeacon('/api/metrics', JSON.stringify({
      ttfb: nav.responseStart - nav.requestStart,
      domReady: nav.domContentLoadedEventEnd - nav.startTime,
      fcp,
      connection: navigator.connection?.effectiveType,
    }));
  }, 1000);
});

RUM araçları: Vercel Analytics, Sentry Performance, Google Analytics 4, Datadog RUM.


13) Bundle Analysis

AracKullanım
webpack-bundle-analyzerWebpack projeleri
rollup-plugin-visualizerVite projeleri
source-map-explorerSource map uzerinden analiz
@next/bundle-analyzerNext.js projeleri
bundlephobia.comPackage boyut kontrolu (online)
bash
# bundlesize ile CI kontrolu
npm install --save-dev bundlesize
json
{
  "bundlesize": [
    { "path": "./dist/assets/*.js", "maxSize": "200 kB", "compression": "gzip" },
    { "path": "./dist/assets/*.css", "maxSize": "50 kB", "compression": "gzip" }
  ]
}

VS Code Import Cost extension'i her import'un boyutunu editor'de gosterir.


14) Performance Budget

Hedef Boyutlar

KaynakButce (gzipped)
Total JS< 200 KB
Initial JS< 100 KB
Total CSS< 50 KB
Images (toplam)< 500 KB
Font (toplam)< 100 KB
Total page weight< 1 MB

Core Web Vitals Hedefleri

MetrikHedef
LCP< 2.5s
INP< 200ms
CLS< 0.1
FCP< 1.8s
TTFB< 800ms
TTI< 3.5s

CI'da Kontrol

javascript
// lighthouserc.js
module.exports = {
  ci: {
    assert: {
      assertions: {
        'categories:performance': ['error', { minScore: 0.9 }],
        'resource-summary:script:size': ['error', { maxNumericValue: 200000 }],
        'resource-summary:stylesheet:size': ['error', { maxNumericValue: 50000 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
      },
    },
  },
};

15) Checklist — Production Oncesi Performans Kontrol Listesi

Gorseller:

  • [ ] Tüm gorseller WebP/AVIF formatinda (fallback ile)
  • [ ] Gorsellere width ve height veya aspect-ratio belirtildi
  • [ ] Above-the-fold gorseller loading="eager" + fetchpriority="high"
  • [ ] Diger gorseller loading="lazy"
  • [ ] Hero image preload ile belirtildi

Fontlar:

  • [ ] WOFF2 formatinda, font-display: swap veya optional
  • [ ] Kritik fontlar preload ile yukleniyor
  • [ ] Font subset yapildi (sadece kullanilan karakterler)

JavaScript:

  • [ ] Route-based code splitting uygulanmis
  • [ ] Tree shaking calisiyor (ES Modules)
  • [ ] Third-party script'ler defer/async/Partytown ile
  • [ ] Bundle boyutu < 200KB gzipped

CSS:

  • [ ] Kullanilmayan CSS kaldirildi (PurgeCSS/Tailwind purge)
  • [ ] Critical CSS inline
  • [ ] CSS < 50KB gzipped

Network ve Cache:

  • [ ] Brotli/gzip compression aktif
  • [ ] CDN kullaniliyor
  • [ ] Gerekli domainler preconnect ile baglandi
  • [ ] Statik asset'ler immutable cache (hash filename)
  • [ ] HTML must-revalidate ile cache'leniyor

Core Web Vitals:

  • [ ] LCP < 2.5s, INP < 200ms, CLS < 0.1
  • [ ] Lighthouse Performance 90+

16) Tips

Premature optimization'dan kacinin. Once çalıştır, sonra olc, sonra optimize et. Tahmin etmeyin, veriyle karar verin.

Measure first. Her optimizasyon oncesi ve sonrasi olcum yapin — iyilesme mi kotulesme mi bilin.

80/20 kurali. Performans kazancinin %80'i su alanlardan gelir:

  1. Gorsel optimizasyonu — En büyük etki, en kolay. Format değiştir, boyut kucult, lazy load.
  2. JavaScript azaltma — Code splitting, tree shaking, gereksiz kütüphane kaldirma.
  3. Font optimizasyonu — Preload, subset, font-display: swap.
  4. Cache ve CDN — Immutable cache, Brotli compression.

Core Web Vitals oncelikli. Google ranking signal. Oncelik: LCP > CLS > INP.

Faydali araclar:

AracTurMaliyet
LighthouseLab testingÜcretsiz
PageSpeed InsightsLab + FieldÜcretsiz
WebPageTestLab testingÜcretsiz
BundlephobiaBundle boyutÜcretsiz
SquooshGorsel optimizasyonÜcretsiz
UnlighthouseToplu site auditÜcretsiz

Ilgili Rehberler

Frontend

Diger Kategoriler

Developer Guides & Technical References