Performance Budget: Performans Bütçesi Oluşturma

Performance Budget: Performans Bütçesi Oluşturma
Performance budget (performans bütçesi), web uygulamanızın performans metriklerini belirli sınırlar dahilinde tutmayı hedefleyen bir stratejidir. Tıpkı mali bütçede olduğu gibi, her kaynak ve metrik için bir limit belirler ve bu limiti aşmamaya çalışırsınız. Bu rehberde performans bütçesi oluşturmayı, izlemeyi ve CI/CD sürecine entegre etmeyi adım adım inceleyeceğiz.
1. Performance Budget Neden Gerekli?
- Performans regresyonunu engeller: Her yeni özellik performansı düşürebilir, bütçe bunu kontrol eder
- Takım farkındalığı: Herkes performans etkisini düşünmek zorunda kalır
- Kullanıcı deneyimi: Hızlı siteler daha yüksek dönüşüm oranına sahiptir
- SEO etkisi: Core Web Vitals sıralama faktörüdür
- Maliyet kontrolü: Daha az veri transferi = daha düşük sunucu maliyeti
2. Budget Türleri
Zamanlama Bazlı Bütçeler
| Metrik | İyi | Orta | Kötü |
|---|---|---|---|
| Time to First Byte (TTFB) | < 200ms | < 500ms | > 500ms |
| First Contentful Paint (FCP) | < 1.8s | < 3.0s | > 3.0s |
| Largest Contentful Paint (LCP) | < 2.5s | < 4.0s | > 4.0s |
| Time to Interactive (TTI) | < 3.8s | < 7.3s | > 7.3s |
| Cumulative Layout Shift (CLS) | < 0.1 | < 0.25 | > 0.25 |
| Interaction to Next Paint (INP) | < 200ms | < 500ms | > 500ms |
Boyut Bazlı Bütçeler
# Önerilen boyut bütçeleri
Toplam sayfa boyutu: < 1.5MB (sıkıştırılmış)
JavaScript toplam: < 300KB (sıkıştırılmış)
CSS toplam: < 100KB (sıkıştırılmış)
Resimler toplam: < 1MB
Font dosyaları: < 100KB
Üçüncü parti script: < 100KB
İstek Bazlı Bütçeler
# Önerilen istek sayıları
Toplam HTTP istekleri: < 50
JavaScript dosyaları: < 10
CSS dosyaları: < 5
Font istekleri: < 4
Üçüncü parti istekler: < 10
3. Budget Oluşturma Adımları
Adım 1: Mevcut Durumu Ölçün
# Lighthouse CI ile mevcut metrikleri ölçün
npm install -g @lhci/cli
lhci autorun --collect.url=https://www.example.com
# WebPageTest API ile
curl "https://www.webpagetest.org/runtest.php?url=https://example.com&f=json&k=YOUR_API_KEY"
Adım 2: Rakip Analizi
# Rakip sitelerinizi ölçün ve ortalamanın %20 altını hedefleyin
# Örnek:
# Rakip ortalama LCP: 3.2s
# Hedefiniz: 3.2s x 0.80 = 2.56s → 2.5s
Adım 3: Budget Tanımlama
// budget.json
[
{
"path": "/*",
"timings": [
{ "metric": "first-contentful-paint", "budget": 1800 },
{ "metric": "largest-contentful-paint", "budget": 2500 },
{ "metric": "interactive", "budget": 3800 },
{ "metric": "cumulative-layout-shift", "budget": 0.1 },
{ "metric": "total-blocking-time", "budget": 200 }
],
"resourceSizes": [
{ "resourceType": "total", "budget": 1500 },
{ "resourceType": "script", "budget": 300 },
{ "resourceType": "stylesheet", "budget": 100 },
{ "resourceType": "image", "budget": 1000 },
{ "resourceType": "font", "budget": 100 },
{ "resourceType": "third-party", "budget": 100 }
],
"resourceCounts": [
{ "resourceType": "total", "budget": 50 },
{ "resourceType": "script", "budget": 10 },
{ "resourceType": "stylesheet", "budget": 5 },
{ "resourceType": "third-party", "budget": 10 }
]
}
]
4. Webpack ile Bundle Budget
// webpack.config.js
module.exports = {
performance: {
maxEntrypointSize: 250000, // 250KB
maxAssetSize: 200000, // 200KB
hints: 'error', // Build'i durdur ('warning' da olabilir)
assetFilter: function(assetFilename) {
return assetFilename.endsWith('.js') || assetFilename.endsWith('.css');
},
},
};
// next.config.js — Next.js experimental budget
/** @type {import('next').NextConfig} */
module.exports = {
experimental: {
// Bundle analyzer
},
// Custom webpack config
webpack: (config, { isServer }) => {
if (!isServer) {
config.performance = {
maxEntrypointSize: 300000,
maxAssetSize: 200000,
hints: 'warning',
};
}
return config;
},
};
5. Lighthouse CI ile Otomatik Kontrol
# .lighthouserc.js
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000/', 'http://localhost:3000/blog'],
numberOfRuns: 3,
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'first-contentful-paint': ['error', { maxNumericValue: 1800 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'total-blocking-time': ['warn', { maxNumericValue: 200 }],
'interactive': ['error', { maxNumericValue: 3800 }],
'resource-summary:script:size': ['error', { maxNumericValue: 300000 }],
'resource-summary:total:size': ['error', { maxNumericValue: 1500000 }],
},
},
upload: {
target: 'temporary-public-storage',
},
},
};
6. CI/CD Pipeline Entegrasyonu
# .github/workflows/performance.yml
name: Performance Budget Check
on:
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install & Build
run: |
npm ci
npm run build
- name: Start server
run: npm start &
- name: Lighthouse CI
uses: treosh/lighthouse-ci-action@v11
with:
configPath: './.lighthouserc.js'
uploadArtifacts: true
temporaryPublicStorage: true
- name: Bundle Size Check
uses: siddharthkp/bundlesize2@v0.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
// bundlesize yapılandırması (package.json)
{
"bundlesize": [
{
"path": ".next/static/chunks/*.js",
"maxSize": "200 kB"
},
{
"path": ".next/static/css/*.css",
"maxSize": "50 kB"
}
]
}
7. Budget Aşımında Aksiyon Planı
# Budget aşıldığında kontrol listesi:
1. Bundle analizi yapın
npx @next/bundle-analyzer
npx webpack-bundle-analyzer stats.json
2. Gereksiz bağımlılıkları tespit edin
npx depcheck
npx bundlephobia [paket-adi]
3. Code splitting uygulayın
- Dynamic import kullanın
- Route bazlı lazy loading
4. Resim optimizasyonu kontrol edin
- WebP/AVIF formatları
- Responsive images (srcset)
- CDN kullanımı
5. Üçüncü parti script'leri değerlendirin
- Gerekli mi? Alternatif var mı?
- async/defer kullanılıyor mu?
- Script boyutu ne kadar?
8. Real User Monitoring (RUM)
// web-vitals ile gerçek kullanıcı verisi toplama
import { onLCP, onFID, onCLS, onINP, onTTFB } from 'web-vitals';
function sendToAnalytics({ name, value, id }) {
const body = JSON.stringify({ name, value, id, page: window.location.pathname });
// Beacon API ile güvenilir gönderim
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/vitals', body);
} else {
fetch('/api/vitals', { body, method: 'POST', keepalive: true });
}
}
onLCP(sendToAnalytics);
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onTTFB(sendToAnalytics);
Sonuç
Performance budget, web performansını sürdürülebilir kılmanın en etkili yoludur. Zamanlama, boyut ve istek bazlı bütçeler belirleyerek performans regresyonunu erken tespit edin. Lighthouse CI ve bundlesize gibi araçlarla CI/CD pipeline'ınıza entegre edin ve her PR'ın performans etkisini otomatik kontrol edin. Bütçe aşımlarında sistematik bir aksiyon planı uygulayın. Unutmayın: performans bir özellik değil, sürekli bir süreçtir.