← Blog
Yazı
· 9 dk· web development

Lighthouse Best Practices Neden 100 Olmuyor? 77 Puanın Gerçek Sebepleri

Lighthouse'ta Best Practices skoru 77 çıktı, ama sitede hata yok mu? Üçüncü taraf çerezler, Issues paneli, source map'ler, güvenlik başlıkları ve en sık yapılan hata: ölçümü localhost'ta almak.

77 Puan: Önce Panik, Sonra Okuma

Bu sitenin sertifikalar sayfasını Lighthouse'tan geçirdiğimde tablo şöyleydi: Accessibility 100, SEO 100, Performance 81 ve Best Practices 77. İlk tepki "bir şeyi yanlış yapıyorum" oluyor. Ama raporu satır satır okuyunca, skorun önemli bir kısmının koddaki bir hatadan değil, ölçümün kendisinden ve bilinçli tercihlerden geldiği ortaya çıktı.

Kısa cevap

Lighthouse'u localhost'ta değil, canlı sitede ve gizli pencerede çalıştırın. Best Practices'te puanı genelde üçüncü taraf çerezler, tarayıcı uyarıları ve source map eksikliği düşürür. "Trust and Safety" başlığı altındaki maddeler ise bilgi amaçlıdır.

En Sık Hata: Ölçümü Development Modunda Almak

Rapor http://localhost:3000 üzerinde, yani next dev çalışırken alınmıştı. Development modunda:

  • JavaScript minify edilmez ("Minify JavaScript: 371 KiB" uyarısı buradan),
  • hot reload ve hata ayıklama kodu pakete girer ("Reduce unused JavaScript: 750 KiB"),
  • derleme isteğe bağlı yapılır, bu yüzden Speed Index gibi metrikler şişer (10,4 sn),
  • hosting tarafındaki başlıklar (HSTS, X-Frame-Options vb.) hiç gelmez.

Lighthouse da raporun başında uyarıyordu: IndexedDB'de kayıtlı veri varmış ve bu, yükleme performansını etkileyebilirmiş. Tarayıcı eklentileri ve önbellek de sonucu bozar. Bu yüzden ölçümü production build üzerinde, gizli pencerede almak gerekiyor.

Best Practices Skorunu Gerçekten Düşüren Üç Şey

1. Üçüncü taraf çerezler

Raporda "Uses third-party cookies: 1 cookie found" görünüyordu. Kaynağı Google Analytics (Google Tag Manager). Tarayıcılar üçüncü taraf çerezlere giderek daha fazla kısıt getirdiği için Lighthouse bunu işaretliyor.

Seçenekler:

  • Analitiği tamamen kaldırmak,
  • çerezsiz çalışan, gizlilik odaklı bir analitik aracına geçmek,
  • ya da bu maddeyi bilinçli bir tercih olarak kabul etmek.

Ben şimdilik üçüncüsünü seçtim: ziyaretçi verisi, 100 puandan daha değerli.

2. "Issues were logged in the Issues panel"

Chrome DevTools'ta Issues sekmesi, konsoldan ayrı olarak tarayıcının kendi uyarılarını toplar: çerez politikaları, karışık içerik (mixed content), eskimiş (deprecated) API'ler, CORS sorunları. Lighthouse burada kayıt varsa maddeyi başarısız sayar. Çözüm basit: DevTools → Issues sekmesini açın, listelenen her maddeyi kaynağına göre düzeltin. Çoğu zaman yine üçüncü taraf bir script'ten gelir.

3. Source map eksikliği

"Missing source maps for large first-party JavaScript" maddesi, production'daki büyük JS dosyalarınız için source map yayınlamadığınızı söyler. Next.js'te tek satırla açılır:

// next.config.ts
const nextConfig = {
  productionBrowserSourceMaps: true,
};

Ama bunun bir bedeli var: source map'ler, uygulamanızın okunabilir kaynak kodunu herkese açar. Kişisel bir portfolyoda sorun olmayabilir; ticari bir üründe genellikle source map'leri yalnızca hata izleme servisine (Sentry vb.) yüklemek tercih edilir. Ben bu siteyi bilinçli olarak kapalı bıraktım.

"Trust and Safety" Maddeleri: Puan Değil, Öneri

Raporda kırmızı görünmese de dikkat çeken beş madde vardı: CSP, HSTS, COOP, XFO ve Trusted Types. Bunlar bilgi amaçlıdır, yani doğrudan skoru düşürmezler. Ama çoğu birkaç satırlık bir başlıkla çözülebildiği için eklemeye değer.

BaşlıkNe yapar?Zorluk
Strict-Transport-Security (HSTS)Tarayıcıyı siteye her zaman HTTPS ile bağlanmaya zorlarKolay
X-Frame-Options (XFO)Sitenin başka bir sitede iframe içinde açılmasını engeller (clickjacking)Kolay
Cross-Origin-Opener-Policy (COOP)Pencereni başka origin'lerden izole ederKolay (OAuth popup'larına dikkat)
Content-Security-Policy (CSP)Hangi kaynaktan script, stil, görsel yüklenebileceğini sınırlar (XSS koruması)Zor
Trusted TypesDOM'a güvenilmeyen HTML yazılmasını engellerZor

Site Cloudflare Pages üzerinde statik export ile yayınlandığı için başlıkları public/_headers dosyasına eklemek yeterli:

/*
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Cross-Origin-Opener-Policy: same-origin

Vercel'de vercel.json'daki headers alanı, Next.js sunucusunda ise next.config'teki headers() fonksiyonu aynı işi görür.

CSP neden "sonra"?

CSP en güçlü koruma ama yanlış yazıldığında siteyi sessizce bozar. Next.js sayfaya inline script'ler gömer; Google Analytics dış kaynaktan script yükler; JSON-LD yapılandırılmış verisi de inline bir <script> etiketidir. Bunların hepsine izin veren ama yine de anlamlı olan bir CSP için nonce ya da hash tabanlı bir yapı gerekir. Statik export'ta nonce mümkün olmadığından hash yolu kalır. Bu ayrı bir yazının konusu.

Bonus: Performance'taki 441 KiB'lık Görsel Tuzağı

Aynı raporda "Improve image delivery: Est savings of 441 KiB" uyarısı vardı ve bu, gerçek bir sorundu. Site statik export ile yayınlandığı için next.config'te şu ayar açık:

images: {
  unoptimized: process.env.NEXT_OUTPUT_MODE === "export",
}

Statik export'ta Next.js'in görsel optimizasyon sunucusu yoktur. next/image kullansanız bile tarayıcıya orijinal dosya gider. Sonuç: yaklaşık 400 piksellik kartlarda 1935 piksel genişliğinde, 370 KB'lık JPG'ler. Development modunda görseller optimize edildiği için sorun localhost'ta hiç görünmez.

Çözüm, görselleri build öncesinde hazırlamak oldu:

cwebp -q 80 -resize 1200 0 sertifika.jpg -o sertifika.webp

Yedi sertifika görselinin toplamı yaklaşık 1,6 MB'tan 350 KB'a indi. Orijinal PDF ve JPG'ler yine indirme linki olarak duruyor. Link önizlemeleri (Open Graph) için de JPG kullanmaya devam ettim, çünkü bazı platformlar önizlemede WebP göstermiyor.

Kontrol Listesi

  • Lighthouse'u canlı sitede ve gizli pencerede çalıştırın.
  • DevTools → Issues sekmesindeki her maddeyi okuyun.
  • Üçüncü taraf script'leri listeleyin; her birinin gerçekten gerekli olup olmadığına karar verin.
  • Source map'ler için bilinçli bir karar verin: açık mı, sadece hata izleme servisine mi?
  • HSTS, XFO, COOP ve nosniff başlıklarını ekleyin; CSP'yi ayrı ve test edilmiş bir adım olarak planlayın.
  • Statik export kullanıyorsanız görselleri build öncesinde boyutlandırın.

Sonuç

Lighthouse skoru bir hedef değil, bir teşhis aracı. 100 puan için Google Analytics'i kaldırmak ya da kaynak kodunuzu herkese açmak her zaman doğru karar değil. Önemli olan, her kırmızı maddenin neden orada olduğunu bilmek ve gerçek sorunları (bu örnekte gereksiz yere 1,6 MB görsel indirmek) bilinçli tercihlerden ayırabilmek.