Skip to content
ORSEN
Tüm yazılar
Mimari2 dk okuma

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} ve fetchPriority="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.

İlgili yazılar

BİR ŞEYLER İNŞA EDELİM

Bir sonraki ürününüz, kazanan ürün olsun.

30 dakikalık keşif görüşmesinde kapsam, takvim ve yatırım netleşir.