Lighthouse 100 için 7 mimari karar
Production'da 100 puanı yakalamak şanslı bir bug fix değil, ön cepheden alınmış mimari kararların sonucu.
Lighthouse 100, kod taşlanarak değil, mimariyle kazanılan bir sonuç. Her projede aynı 7 kararı baştan veriyor olmamız tesadüf değil — bunlar lansman gecesi 3 puanın peşine düşmek yerine ön cephede alındığında temiz raporu garantiler.
1. Server Components varsayılan
Sayfa interaktivite gerektirmiyorsa client kod gönderme. Marketing, blog, dokümantasyon, e-ticaret kategori sayfaları — hepsi server-only. JS bundle'ın %60-80'i bu kararla iniyor.
// app/[locale]/services/[slug]/page.tsx
export default async function ServicePage({ params }) {
const { locale, slug } = await params;
const service = await getService(locale, slug);
return <ServiceTemplate service={service} />;
}
Pratik kural
"use client" yazmadan önce iki saniye düşün. Gerçekten state mi var, yoksa sadece dekor mu?
2. Image: hep next/image, hep boyut
Her img elementi explicit width ve height ile gelmek zorunda. LCP'yi öldüren tek şey CLS — ve CLS'in en büyük kaynağı boyutsuz görsel.
- Hero görseli için
priority={true}vefetchPriority="high" - Below-fold için
loading="lazy"zaten varsayılan - AVIF + WebP fallback otomatik
3. Font: subset + display swap
Latin-only subset, font-display: swap, next/font ile self-host. 200KB Inter dosyası, doğru kurulduğunda 18KB'a iniyor.
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"], display: "swap" });
Türkçe içerik için subsets: ["latin", "latin-ext"] çünkü ş, ğ, ı karakterleri latin-ext'te.
4. CSS: tek dosya, kritik gömülü
Tailwind v4 ile bundle başlı başına bir kritik path. Atomic CSS, route başına 5-15KB arası — Next 15 otomatik inline ediyor 14KB'a kadar.
5. Animasyon: GPU layer, ama tek hat
Aurora gradient blob'lar, parallax, micro-interaction'lar — hepsi transform + opacity üzerinden. top veya left animasyonu Lighthouse'da değil, gerçek kullanıcıda kasıyor.
.aurora-blob {
transform: translate3d(0, 0, 0);
will-change: transform;
animation: aurora-shift 32s ease-in-out infinite;
}
Yaygın hata
backdrop-filter: blur(24px) sticky header'da kullanıldığında scroll FPS'i ikiye böler. blur(12px) yeterli, gerisi kalitede fark yaratmıyor.
6. Third-party'ler: hep next/script strategy
Analytics, chat widget, tag manager — hepsi strategy="afterInteractive" veya "lazyOnload". Hiçbiri başlangıçta yüklenmemeli. Plausible kullanıyorsak zaten 1KB; GTM yerine doğrudan GA4 + next/third-parties bir tık daha hafif.
7. JSON-LD: build-time, runtime değil
Schema markup'ı sayfa render'ında üret, client'a gönderme. Server Component'ten doğrudan <script type="application/ld+json"> çıktısı.
export default function Page() {
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(orgSchema),
}}
/>
<Hero />
</>
);
}
Bunlar yedi karar; sekizincisi de var: ölç. CI'da Lighthouse koş, mobile preset üzerinden, performance budget koy. Üretim için hedef sabit; düşüş regression demek, fix değil.