Vercel Analytics, @next/bundle-analyzer ve Lighthouse CI üçlüsüyle Next.js App Router projelerinde her deploy sonrası Core Web Vitals regresyonunu otomatik yakalamak için adım adım kurulum ve tanılama akışı.

Next.js App Router'da Performance Regression Nasıl İzlenir?

Next.js App Router, Pages Router'dan köklü biçimde farklı bir render mimarisi getirir. Server Components, streaming, Suspense boundary'leri ve yeni route segmentleri, performans sorunlarının hangi katmanda birikeceğini önceden tahmin etmeyi güçleştirir. Deploy sayısı arttıkça bu katmanlar üzerindeki değişikliklerin kümülatif etkisi fark edilmeden büyüyebilir; bir sabah LCP değerinin 400ms'nin üzerine çıktığını, ama bunun hangi commit'te gerçekleştiğini bilemediğinizi fark edebilirsiniz.

Regresyonu erken yakalamak, üç farklı veri katmanını birbirine bağlamayı gerektirir. Gerçek kullanıcıların deneyimini Vercel Analytics ve SpeedInsights ölçer. Her deploy'daki bundle büyümesini @next/bundle-analyzer raporlar. CI hattında otomatik kalite kapısı görevi gören Lighthouse CI ise pull request onaylanmadan önce eşik ihlallerini yakalar. Bu üç araç birbirini tamamlar; yalnızca biriyle çalışmak körlük noktaları bırakır.

Kurulum, her aracın ne zaman işe yarayıp ne zaman yanıltabileceğini ayırır. Regresyon yakalandığında izlenecek tanılama akışı, ölçümden sonra hangi katmana bakılacağını da netleştirir.

App Router'ın performans izlemeyi farklı kılan mimarisi

Server Components, App Router'da varsayılan davranıştır. "use client" direktifi olmadan yazdığınız her bileşen sunucuda çalışır ve client bundle'a dahil edilmez. Bu, client JavaScript boyutunu önemli ölçüde küçültmek için güçlü bir araçtır. Ancak hatalı bir bağımlılık eklediğinizde - örneğin ağır bir animasyon kütüphanesini "use client" sınırını geçen bir sarmalayıcı bileşene koyduğunuzda - LCP ve FCP değerleri sessizce bozulabilir; bu bozulma Pages Router'daki kadar açık sinyaller vermez.

Streaming, Lighthouse'u yanıltır. Bir sayfanın ilk ekranında Suspense ile sarılmış bir bileşen varsa ve LCP öğesi bu bileşenin içindeyse, Lighthouse bu durumu gerçek kullanıcının gördüğü gibi simüle edemeyebilir. Yalnızca lab ölçümüne güvenmek bu yüzden yetersiz kalır; alan verisi (CrUX ve Vercel SpeedInsights) streamed sayfalar için daha gerçekçi bir tablo sunar. Lighthouse skoru yüksek ama kullanıcı yavaş hissediyorsa bu iki veri kaynağı arasındaki açıklığı incelemeye değer.

Bir diğer önemli fark, route segment düzeyindeki cache mekanizmasıdır. fetch() çağrılarına verilen revalidate değeri veya dynamic = 'force-dynamic' direktifi, hem sunucu yükünü hem de TTFB'yi doğrudan etkiler. Bu ayarların refactor sırasında değişmesi, LCP ve TTFB'de ani sıçramalara neden olabilir ancak bundle boyutunda herhangi bir iz bırakmaz.

Vercel Analytics ve SpeedInsights ile alan verisi toplamak

Vercel Analytics, gerçek kullanıcı oturumlarından LCP, FCP, CLS ve TTFB değerleri toplar. SpeedInsights paketi ise bu metrikleri daha ayrıntılı şekilde sayfa bazında kırar. Kurulum iki adımdan oluşur.

Önce paketleri ekleyin:

npm install @vercel/analytics @vercel/speed-insights

Ardından app/layout.tsx dosyanıza bileşenleri ekleyin:

import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
        <SpeedInsights />
      </body>
    </html>
  );
}

Vercel panosunda "Speed Insights" sekmesi, her sayfanın P75 değerlerini deploy geçmişiyle yan yana gösterir. Regresyon için anlamlı referans noktası P75'tir; ortanca değer iyi görünse bile P75'in bozulması kullanıcıların önemli bir bölümünün olumsuz etkilendiğine işaret eder. Günde yüzün altında oturum alan sayfalarda alan verisi birikimine zaman tanımak gerekir; düşük trafikli sayfalarda bu yöntem istatistiksel olarak yetersiz kalabilir.

@next/bundle-analyzer ile bundle büyümesini yakalamak

@next/bundle-analyzer, her build'den sonra etkileşimli bir treemap oluşturur. Hangi modülün kaç kilobayt yer kapladığını, hangi "use client" bileşeninin beklenmedik bağımlılıklar çektiğini bu görünümde anlık olarak fark edebilirsiniz.

Kurulum:

npm install --save-dev @next/bundle-analyzer

next.config.js dosyanıza entegre edin:

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

module.exports = withBundleAnalyzer({
  // mevcut next.js ayarları
});

Analizi çalıştırmak için:

ANALYZE=true npm run build

Bu komut üç ayrı HTML raporu açar: client bundle, server bundle ve edge bundle. Çoğu regresyon client bundle'da ortaya çıkar. Treemap'te beklenmedik biçimde büyük bir düğüm görürseniz - örneğin yalnızca bir formdaki tarih seçici için 200KB'lık bir kütüphane - sorunun kökü genellikle oradadır. Bu araç, CI ortamında değişkeni otomatik ayarlamadıkça her PR'da çalışmaz; aşağıdaki bölümde CI entegrasyonunu ele alıyorum.

Bundle analyzer gereksiz olduğu durumlar da var. Sunucu tarafında çalışan ve client bundle'a hiç girmeyen bir bileşendeki bağımlılık büyümesi bu araçta görünmez. Server-side bağımlılık büyümesinin TTFB üzerine etkisini izlemek için Vercel analytics TTFB eğrisine bakmak daha doğru bir yaklaşımdır. Next.js projelerindeki darboğazları bulmak için iki veri kaynağını birlikte okumak gerekir.

Lighthouse CI ile otomatik kalite kapısı kurmak

Lighthouse CI, her pull request için Lighthouse çalıştırır ve belirlenen eşiklerin altına düşen bir skor varsa CI'yi kırmaz - isterseniz kırabilirsiniz. Temel kullanımda bir uyarı üretir ve geçmişe kayıt düşer.

Kurulum:

npm install --save-dev @lhci/cli

Proje kökünde lighthouserc.js dosyası oluşturun:

module.exports = {
  ci: {
    collect: {
      startServerCommand: 'npm run start',
      url: ['http://localhost:3000/', 'http://localhost:3000/urunler'],
      numberOfRuns: 3,
    },
    assert: {
      assertions: {
        'categories:performance': ['warn', { minScore: 0.8 }],
        'first-contentful-paint': ['error', { maxNumericValue: 2000 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
      },
    },
    upload: {
      target: 'temporary-public-storage',
    },
  },
};

GitHub Actions workflow dosyanıza ekleyin:

- name: Run Lighthouse CI
  run: |
    npm run build
    npm run start &
    sleep 5
    npx lhci autorun

Üç çalıştırma (numberOfRuns: 3) medyan değeri alır; tek çalıştırma gürültülü sonuçlar verebilir. LCP eşiği olarak 2500ms kullanmak Google'ın "iyi" sınırıyla örtüşür, ancak mevcut üretim değeriniz çok daha iyiyse bu eşiği daha sıkı tutmak regresyonu daha erken yakalar. Örneğin üretimde P75 LCP değeriniz 1200ms ise 2500ms eşiği regresyonu ancak iki kat kötüleştikten sonra yakalar; eşiği 1600ms'ye çekmek daha anlamlı olur.

Lighthouse CI'nin sınırı şuradadır: sunucu ortamı üretim Vercel altyapısıyla birebir aynı değildir. CI'deki Lighthouse sonuçları trend izleme için değerlidir, ancak mutlak sayılar üretim değerleriyle uyuşmaz. Araç, "bu PR'dan önce 1100ms'ydi, şimdi 1900ms" gibi görece bozulmaları yakalamada güçlüdür.

Performans bütçesi tanımlamak ve eşikleri kalibre etmek

Eşikler sabit sayılar değildir. Başlangıç noktası olarak mevcut P75 değerlerinizin yüzde on üzerinde bir sınır belirleyin; bu hem gerçekçi hem de anlamlı bir buffer sağlar. Daha dar bir buffer (yüzde beş) sık sık sahte alarm üretir; daha geniş bir buffer (yüzde yirmi beş) regresyonu geç yakalar.

Bundle boyutu için ayrı bir bütçe tanımlamak, araç karmaşasını azaltır. next.config.js içinde experimental bundlePagesExternals ayarıyla birlikte harici bir bütçe dosyası kullanabilirsiniz:

// budget.json
[
  {
    "path": "/_next/static/chunks/pages/**",
    "timings": [
      { "metric": "interactive", "budget": 5000 }
    ],
    "resourceSizes": [
      { "resourceType": "script", "budget": 300 },
      { "resourceType": "total", "budget": 600 }
    ]
  }
]

Bu bütçe dosyasını Lighthouse CI konfigürasyonuna dahil edebilirsiniz. Sayıları belirlerken ekibin performans hedeflerini ve kullanıcı tabanının cihaz profilini gözetmek gerekir. Mobil ağırlıklı bir kitleye hizmet ediyorsanız script bütçesini daha sıkı tutmak mantıklıdır; mobil kullanıcılar aynı JavaScript boyutunu masaüstü kullanıcılarına kıyasla çok daha yavaş işler. Aylık site hızı takibinde bütçe eşiklerini periyodik olarak gözden geçirmek, drifti önlemenin en pratik yoludur.

Bütçe aşımı her zaman acil müdahale gerektirmez. İncelenmesi gereken soru şudur: bütçe aşımının arkasında bir özellik kararı mı var, yoksa dikkat edilmeyen bir bağımlılık artışı mı? Kasıtlı karar ise bütçeyi güncellemek tutarlılığı korur; farkında olunmayan bir artışsa kök nedeni bulmak önceliklidir.

Deploy sonrası regresyon tespit etme akışı

Üç araçtan gelen sinyal bir araya geldiğinde aşağıdaki sırayı izlemek regresyonun kaynağını hızla daraltır.

İlk adım, Vercel SpeedInsights panosunda son deploy'un P75 değerlerini önceki deploy ile karşılaştırmaktır. Belirgin bir sıçrama varsa hangi metriğin etkilendiğine bakın: yalnızca LCP bozulduysa render tarafında bir sorun var demektir; TTFB de birlikte yükseldiyse sunucu tarafını - cache ayarları, sunucu bileşen veri çekme süresi - incelemeye başlamak gerekir. TTFB ile FCP arasındaki boşluk render zincirindeki sorunların ayırt edici işaretidir.

İkinci adım, Lighthouse CI geçmişini açıp hangi PR'ın skoru kırdığını bulmaktır. Sayısal değerler değil trend önemlidir; birden fazla küçük artış birikimli bir regresyona işaret edebilir. Hangi route'un bozulduğu burada netleşir.

Üçüncü adım, o PR'ın bundle değişikliklerini @next/bundle-analyzer ile incelemektir. Lokal ortamda ANALYZE=true npm run build çalıştırıp treemap'i açın. Sorunlu bileşenin hangi bağımlılığı çektiğini görselleştirin. Yeni bir "use client" bileşeni büyük bir kütüphaneyle mi birlikte geldi? Dinamik import yerine statik import kullanıldı mı?

Dördüncü adım, sorunu izole ettikten sonra değişikliği geri almak veya düzeltmek ve CI'yi yeniden tetiklemektir. Lighthouse CI geçerse ve Vercel SpeedInsights sonraki gün değerler için normale döndüğünü gösterirse regresyon kapatılmış demektir. Performans sorununu düzeltirken önce neye bakılacağını anlamak, bu adımları gereksiz tekrarsız yürütmek için kritiktir.

Sık karşılaşılan tuzaklar ve yanlış pozitifler

Lighthouse CI'yi yalnızca ana sayfaya karşı çalıştırmak yaygın bir hatadır. E-ticaret projelerinde ürün listeleme ve ürün detay sayfaları, ana sayfadan tamamen farklı bir bileşen ağacına sahiptir; regresyon çoğunlukla orada ortaya çıkar. E-ticaret performansı için öncelikli adımlar arasında izlemeye alınacak sayfa listesini belirlemek öne çıkar.

Alan verisi gecikmeli gelir. Bir regresyonu deploy'dan hemen sonra SpeedInsights'ta göremeyebilirsiniz; yeterli oturum birikmesi birkaç saat alabilir. Bu süre boyunca Lighthouse CI'nin senkron geri bildirimi değerlidir, ancak mutlak sayılara değil trenddeki yönelime bakılmalıdır.

Yanlış pozitifler genellikle CI ortamındaki kaynak kısıtlamalarından kaynaklanır. Lighthouse'un simüle ettiği CPU hızını belirleyen throttlingMethod ayarı CI ortamına göre farklılaştığında aynı kod tabanı çok farklı skorlar verebilir. Bunu kontrol altına almak için lighthouserc.js içinde throttling bloğunu açıkça tanımlayın; varsayılan simüle edilmiş throttling yerine devtoolsCPUThrottling: 4 gibi sabit bir değer kullanmak tekrarlanabilirliği artırır.

CLS regresyonları bazen bundle veya TTFB sorunlarından bağımsız olarak ortaya çıkar. Yeni eklenen bir reklam alanı, geç yüklenen bir font veya boyutsuz bir görsel bu kategoriye girer. LCP görselini bulmak ve görselin boyut özniteliklerini kontrol etmek CLS tuzaklarını erkenden kapatan bir alışkanlıktır.

Ölçüm sürekliliği ve ekip içi uyum

Araçlar kurulduktan sonra asıl zorluk, bu verilerin düzenli incelenmesi alışkanlığını oluşturmaktır. Vercel panosunu açıp SpeedInsights sekmesini incelemek, sprint retrospektiflerine veya haftalık teknik toplantılara dahil edildiğinde reaktif değil proaktif bir kapasite oluşur.

Lighthouse CI uyarıları PR yorumlarına otomatik ekleniyor olsa da geliştiricilerin bu yorumları atlaması olasıdır. Kritik eşikler için warn yerine error kullanmak, CI'yi kırmak ve birleştirmeyi engellemek daha güçlü bir zorunluluk yaratır. Hangi metriğin error, hangisinin warn olacağı ekip içinde tartışılmalı ve belgelenmelidir; keyfi eşikler zamanla görmezden gelinir.

Performans bütçesini ve eşikleri kod deposuna almak, kararların ve gerekçelerinin takip edilmesini sağlar. lighthouserc.js ve budget.json dosyaları PR süreçlerinden geçtiğinde kimin neyi neden değiştirdiği kayıt altında olur. Aylık takip alışkanlığı bu kayıtların periyodik olarak gözden geçirilmesiyle beslenir.

Vercel Analytics, @next/bundle-analyzer ve Lighthouse CI üçlüsü, App Router projelerinde regresyonu deploy anında yakalamak için yeterli bir temel kurar. Üç aracı aynı anda devreye almak zorunda değilsiniz; Lighthouse CI ile başlamak en hızlı kazanımı getirir, alan verisi birikmesi için birkaç hafta beklemek gerekebilir.

App Router'ın mimarisi performans kazanımları için güçlü araçlar sunar, ancak bu araçlar dikkat edilmezse regresyon için de zemin hazırlar. Server Components sınırı yanlış çizilmiş bir bileşen, bundle analyzer çalıştırılmadan fark edilmeyebilir; bir route segmentinin cache davranışı değiştirilmiş ama TTFB eğrisi izlenmiyor olabilir. İzleme olmayan optimizasyon zamanla sürüklenmeye dönüşür.

Tanımlı eşikler, otomatik kontroller ve düzenli alan verisi incelemesiyle bu sürüklenmeyi engellemek mümkündür. Her deploy, bir öncekiyle karşılaştırılabilir bir veri noktasına dönüştüğünde regresyon artık sürpriz olmaktan çıkar.