Next.js, SSR ve Mikro-Frontendler

Modern web mimarisinde SSR (Sunucu Taraflı Oluşturma), SSG, React Server Components ve Micro-Frontend nedir? Core Web Vitals hızı ve SEO uyumlu arayüzler.

Yozel

12 dakika

Next.js, SSR ve Mikro-Frontendler
İçindekiler (15)

Web uygulama geliştirme mimarisi son on beş yılda devasa bir sarkaç gibi iki uç arasında gidip geldi. Geleneksel çok sayfalı sunucu uygulamalarından (PHP, JSP, ASP.NET) tamamen tarayıcıda çalışan Tek Sayfalı Uygulamalara (SPA - Single Page Applications) geçiş, kullanıcı etkileşimini zenginleştirse de beraberinde devasa JavaScript paket boyutları (bundle size), boş beyaz ekran süreleri, SEO indeksleme krizleri ve düşük mobil performans getirdi. Günümüzde ise Next.js App Router, React Server Components (RSC), Streaming SSR (Akışlı Sunucu Taraflı Oluşturma) ve Mikro-Frontend (Micro-Frontends) mimarileriyle bu sarkacın en verimli denge noktasına ulaşıldı. Modern uygulama ve yazılım projelerinde artık "sunucu mu yoksa istemci mi?" sorusu yerine, "hangi bileşen hangi katmanda render edilmeli?" sorusu soruluyor.

Bu kapsamlı teknik rehberde; CSR, SSR, SSG ve ISR oluşturma (rendering) stratejilerinin derinlemesine mekaniklerini, React Server Components ile sıfır paket boyutlu (zero-bundle-size) bileşen mimarisini, Seçici Hidrasyon (Selective Hydration) teknolojisini ve büyük ölçekli mühendislik ekiplerinin bağımsız dağıtım yapabilmesini sağlayan Mikro-Frontend (Module Federation, İframe, Web Components, Edge Composition) desenlerini tüm ayrıntılarıyla inceleyeceğiz.

1. Web Oluşturma (Rendering) Stratejilerinin Evrimi: CSR, SSR, SSG ve ISR

Modern bir web sayfasının kullanıcı ekranında piksellere dönüşüp tıklanabilir (etkileşimli) hale gelmesi sürecinde dört temel oluşturma (rendering) paradigması kullanılır. Bir sistem mimarının her bir sayfa veya rota (route) için doğru stratejiyi seçmesi, hem sunucu maliyetlerini hem de organik arama motoru sıralamalarını doğrudan belirler.

  • CSR (Client-Side Rendering - İstemci Taraflı Oluşturma): Sunucu tarayıcıya yalnızca boş bir `<div id="root"></div>` kabuğu ve megabaytlarca büyüklükte bir JavaScript paketi gönderir. Tarayıcı önce JS dosyasını indirir, ayrıştırır (parse), çalıştırır, ardından API'den verileri çeker ve DOM'u oluşturur. İlk yükleme (FCP ve LCP) yavaştır ve arama motoru botları için tarama bütçesi (crawl budget) kaybı yaratır.
  • SSR (Server-Side Rendering - Sunucu Taraflı Oluşturma): Kullanıcı sayfayı talep ettiği anda (request-time), Node.js veya Edge çalışma zamanı veritabanından güncel veriyi çeker, React/Vue bileşenlerini çalıştırarak tam dolu HTML çıktısını üretir ve tarayıcıya gönderir. Kullanıcı milisaniyeler içinde içeriği görür; ardından tarayıcı JavaScript'i indirerek HTML'e olay dinleyicilerini (event listeners) bağlar. Bu işleme Hidrasyon (Hydration) denir.
  • SSG (Static Site Generation - Statik Site Üretimi): Tüm HTML sayfaları uygulama derlenirken (build-time) bir kez üretilir ve doğrudan CDN (İçerik Dağıtım Ağı) uç noktalarına dağıtılır. Çalışma zamanında sunucu maliyeti sıfıra yakındır ve TTFB (Time to First Byte) süresi rakipsizdir. Ancak sık değişen yüz binlerce ürün sayfasında derleme süreleri saatlere çıkabilir.
  • ISR (Incremental Static Regeneration - Artımlı Statik Yeniden Üretim): SSG'nin hızı ile SSR'ın güncelliğini birleştiren hibrit modeldir. Sayfa CDN önbelleğinden statik olarak sunulurken, belirlenen süre (örneğin `revalidate: 60` saniye) dolduğunda veya bir CMS/ERP webhook tetiklemesi (`revalidateTag` / `revalidatePath`) geldiğinde arka planda yalnızca o sayfa sessizce yeniden üretilir (Stale-While-Revalidate).
CSR, SSR, SSG ve ISR Web Render Stratejileri ve Core Web Vitals Farkı
CSR, SSR, SSG ve ISR oluşturma stratejileri; İlk Bayt Süresi (TTFB), En Büyük İçerikli Boyama (LCP) ve Etkileşime Geçiş (INP) metriklerini doğrudan şekillendirir.

2. Geleneksel SSR'ın Darboğazları ve React Server Components (RSC) Devrimi

Geleneksel SSR (örneğin Next.js Pages Router `getServerSideProps`), CSR'ın ilk boyama (First Paint) sorununu çözmüş olsa da üç büyük mimari darboğaz barındırıyordu:

  1. Her Şeyi Çekmeden Hiçbir Şeyi Gösterememe: Sunucu, sayfadaki en yavaş API çağrısı tamamlanana kadar HTML göndermeye başlayamazdı.
  2. Her Şeyi İndirmeden Hidrasyon Yapamama: Tarayıcı, sayfadaki tüm bileşenlerin JavaScript kodunu indirmeden React DOM ağacını hidrate edemezdi (All-or-Nothing Hydration).
  3. Çift Veri Gönderimi (Double Data Payload): Hem oluşturulan HTML hem de hidrasyon için gereken `__NEXT_DATA__` JSON yükü aynı anda tarayıcıya gönderilerek ağ trafiğini ikiye katlardı.

React Server Components (RSC): Sıfır Paket Boyutlu Bileşenler

React 18/19 ve Next.js App Router ile hayatımıza giren React Server Components (RSC), bileşenleri iki ayrı türe ayırarak bu darboğazı kökten çözdü: Sunucu Bileşenleri (Server Components) ve İstemci Bileşenleri (`"use client"` - Client Components).

Sunucu bileşenleri yalnızca ve yalnızca sunucuda çalışır; kodları asla tarayıcıya gönderilen JavaScript paketine (bundle) dahil edilmez! Bu sayede bir Sunucu Bileşeni içinde ağır bir Markdown ayrıştırıcı, tarih kütüphanesi veya doğrudan veritabanı/ORM istemcisi (Prisma, Drizzle) kullandığınızda, kullanıcının tarayıcısına 0 KB JavaScript gönderilir.

// Next.js App Router: Sunucu Bileşeni (Server Component) ve Suspense ile Akışlı SSR (Streaming SSR)
import { Suspense } from "react";
import { db } from "@/lib/database";
import AddToCartButton from "./AddToCartButton"; // "use client" bileşeni
import ProductReviewsSkeleton from "./ProductReviewsSkeleton";
import ProductReviews from "./ProductReviews";

export default async function ProductDetailPage({ params }: { params: { slug: string } }) {
  // Doğrudan sunucuda veritabanı sorgusu - Tarayıcıya 0 KB JS gider!
  const product = await db.products.findUnique({ where: { slug: params.slug } });

  if (!product) {
    return <div>Ürün bulunamadı.</div>;
  }

  return (
    <main className="product-layout">
      <section className="product-hero">
        <h1>{product.title}</h1>
        <p className="price">{product.price} TL</p>
        {/* Yalnızca etkileşimli sepet butonu tarayıcıda hidrate edilir */}
        <AddToCartButton productId={product.id} stock={product.stock} />
      </section>

      {/* Yavaş yüklenen yorumlar ana sayfayı bloklamaz; HTTP chunked streaming ile akar */}
      <Suspense fallback={<ProductReviewsSkeleton />}>
        <ProductReviews productId={product.id} />
      </Suspense>
    </main>
  );
}

Streaming SSR (Akışlı SSR) ve Seçici Hidrasyon (Selective Hydration)

HTTP/1.1 `Transfer-Encoding: chunked` ve HTTP/2-3 akış (streaming) yeteneklerini kullanan Streaming SSR, React `<Suspense>` sınırlarıyla birleştiğinde mucizevi bir kullanıcı deneyimi yaratır. Yukarıdaki örnekte ürün başlığı ve fiyatı 20 milisaniyede hazır olurken, kullanıcı yorumları servisi 600 milisaniye sürüyorsa; sunucu ilk 20 milisaniyede sayfa kabuğunu ve ürün bilgisini tarayıcıya gönderir. Yorumlar alanında ise iskelet görünümü (skeleton) yer alır. 600 milisaniye sonra sunucu, açık kalan aynı HTTP bağlantısı üzerinden yorumların HTML parçasını ve küçük bir `<script>` etiketini akıtarak iskeletin yerine gerçek yorumları anında yerleştirir.

Üstelik Seçici Hidrasyon (Selective Hydration) sayesinde, sayfanın alt kısmındaki bir bileşen henüz hidrate edilmemiş olsa bile kullanıcı o bileşene tıkladığı anda React öncelik sırasını değiştirir ve önce kullanıcının tıkladığı bileşeni hidrate ederek etkileşimi kesintisiz tamamlar. Bu mimari, Core Web Vitals metriklerinden LCP (Largest Contentful Paint) ve INP (Interaction to Next Paint) skorlarını zirveye taşır.

React Server Components ve Mikro-Frontend Mimarisi Takım Ölçekleme
Büyük ölçekli kurumsal organizasyonlarda Mikro-Frontend mimarisi, farklı önyüz ekiplerinin birbirini bloklamadan bağımsız derleme ve canlıya alma (CI/CD) yapmasını sağlar.

3. Mikro-Frontend (Micro-Frontends) Mimarisi: Önyüz Monolitini Parçalamak

Arka uç dünyasında monolitik uygulamalar yıllar önce bağımsız mikroservislere (Sipariş Servisi, Ödeme Servisi, Arama Servisi, Katalog Servisi) bölündü. Ancak birçok büyük teknoloji şirketinde 50 ila 200 önyüz geliştiricisi hâlâ tek bir devasa React/Next.js kod tabanı (Frontend Monolith) üzerinde çalışmaya devam ediyor. Bu durum şu organizasyonel darboğazları doğurur:

  • Küçük bir buton metni değişikliği için bile tüm uygulamanın 25 dakika süren CI/CD boru hattından geçmesi.
  • Ödeme ekibinin yaptığı bir hatanın ana sayfa veya ürün arama akışını çökertmesi (Single Point of Failure).
  • Farklı ekiplerin kütüphane yükseltmelerinde (örneğin React 18'den 19'a geçiş) birbirini aylarca beklemesi.

Mikro-Frontend (Micro-Frontend Architecture), mikroservis ilkelerini tarayıcı ve sunucu arayüz katmanına taşır: Web uygulaması, her biri uçtan uca bir iş alanından (Vertical Domain - örn. Arama, Sepet/Checkout, Hesabım, Ürün Detay) sorumlu otonom ekipler tarafından geliştirilen, test edilen ve bağımsız olarak canlıya alınan (independently deployable) modüllerin birleşimi olarak kurgulanır.

Mikro-Frontend Entegrasyon Desenleri

Bir mikro-frontend mimarisi kurgularken bileşenlerin nerede ve nasıl birleştirileceğine (composition) göre dört ana desen kullanılır:

  1. Derleme Zamanı Entegrasyonu (Build-Time / NPM Packages): Her ekip kendi modülünü bir NPM paketi olarak yayınlar; ana kabuk uygulama (Host Shell) bunları `package.json` içine alır. Kurulumu basittir ancak bir alt paket güncellendiğinde ana uygulamanın yeniden derlenip dağıtılması gerekir; gerçek bağımsız dağıtım sağlamaz.
  2. Çalışma Zamanı Module Federation (Webpack 5 / Rspack Module Federation): En popüler modern yaklaşımdır. Ana uygulama (Host), alt uygulamaların (Remotes) derlenmiş modüllerini çalışma zamanında (`remoteEntry.js`) dinamik olarak ağ üzerinden yükler. React, React-DOM veya tasarım sistemi (Design System) gibi ortak bağımlılıklar singleton olarak paylaşıldığı için tarayıcıya iki kez React indirilmez.
  3. Sayfa / Rota Bazlı Çoklu Bölge (Next.js Multi-Zones & Edge Routing): Kullanıcı `/urunler/*` adresine gittiğinde Cloudflare Workers, Nginx veya AWS CloudFront isteği Katalog ekibinin Next.js uygulamasına; `/sepet/*` adresine gittiğinde ise Ödeme ekibinin Next.js uygulamasına yönlendirir. Ekipler birbirinden %100 izoledir ve en yüksek SEO/SSR performansını verir.
  4. Web Components (Custom Elements & Shadow DOM): Çerçeveden bağımsız (framework-agnostic) izolasyon gerektiğinde kullanılır. Örneğin eski bir Angular uygulamasının içine yeni bir React veya Vue bileşenini `<checkout-widget>` özel HTML etiketi olarak gömmek ve CSS çakışmalarını Shadow DOM ile engellemek için idealdir.
// Webpack 5 / Rspack Module Federation: Host (Ana Kabuk) Yapılandırma Örneği
const { ModuleFederationPlugin } = require("@module-federation/enhanced");

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: "shell_host",
      remotes: {
        catalogApp: "catalogApp@https://cdn.ornek.com/catalog/remoteEntry.js",
        checkoutApp: "checkoutApp@https://cdn.ornek.com/checkout/remoteEntry.js",
      },
      shared: {
        react: { singleton: true, requiredVersion: "^19.0.0" },
        "react-dom": { singleton: true, requiredVersion: "^19.0.0" },
      },
    }),
  ],
};

4. Mikro-Frontendlerde Durum Yönetimi (State Sharing) ve Tasarım Sistemi Uyumu

Mikro-frontend mimarisinde yapılan en ölümcül hata, tüm mikro uygulamaları dev bir merkezi Redux/Zustand deposuna (global store) bağlamaktır. Eğer iki mikro-frontend aynı bellek içi duruma sıkı sıkıya bağlıysa (tightly coupled), artık bir mikro-frontend değil, dağıtık bir monolit (distributed monolith) inşa etmişsiniz demektir.

Bağımsızlığı korumak için mikro-frontendler arası iletişim şu üç gevşek bağlı (loosely coupled) kanal üzerinden yürütülmelidir:

  • URL ve Sorgu Parametreleri (Single Source of Truth): Filtreler, sayfalama ve aktif sekme gibi durumlar doğrudan URL'de tutulmalıdır.
  • Tarayıcı Yerel Olayları (`CustomEvent` API): Örneğin Ürün Detay mikro uygulaması sepete ürün eklendiğinde `window.dispatchEvent(new CustomEvent('cart:item-added', { detail: { sku, qty } }))` yayınlar; üst menüdeki (Header) Mini-Sepet mikro uygulaması bu olayı dinleyerek kendi sayacını günceller.
  • Ortak Tasarım Sistemi (Design Tokens & UI Kit): Kullanıcı farklı ekiplerin geliştirdiği modüller arasında gezinirken yazı tipi, boşluk veya renk farkı hissetmemelidir. CSS değişkenleri (Design Tokens) ve atomik UI bileşenleri merkezi bir kütüphaneden versiyonlanarak sunulmalıdır.

5. Next.js 4 Katmanlı Önbellekleme (Caching) Mimarisi ve Edge Middleware

Modern SSR ve React Server Components mimarisinde yüksek performansı sürdürülebilir kılmanın sırrı, her kullanıcı isteğinde sıfırdan hesaplama yapmak yerine çok katmanlı önbellekleme (multi-tier caching) stratejisini doğru yapılandırmaktır. Next.js App Router mimarisinde birbirini tamamlayan dört farklı önbellek katmanı bulunur:

  • Request Memoization (İstek Hafızalama - Sunucu Belleği): Tek bir HTTP isteğinin (render pass) yaşam döngüsü boyunca aynı URL ve parametrelerle yapılan `fetch()` çağrılarını React otomatik olarak tekilleştirir (deduplicate). Böylece hem `generateMetadata` fonksiyonunda hem de alt bileşenlerde aynı ürün verisini çektiğinizde veritabanına iki kez gidilmez.
  • Data Cache (Veri Önbelleği - Kalıcı Sunucu Önbelleği): Kullanıcı istekleri ve hatta dağıtımlar (deployments) arasında kalıcı olan sunucu tarafı veri önbelleğidir. `fetch(url, { next: { revalidate: 3600, tags: ['products'] } })` şeklinde etiketlenerek kullanılır ve ürün fiyatı değiştiğinde `revalidateTag('products')` çağrısıyla milisaniyeler içinde temizlenir.
  • Full Route Cache (Tam Rota Önbelleği - Derleme ve ISR): Statik olarak işaretlenen rotaların hem oluşturulmuş HTML çıktısını hem de RSC Payload (React Server Component ikili ağaç verisi) çıktısını sunucu diskinde veya paylaşımlı Redis katmanında saklar.
  • Client-Side Router Cache (İstemci Tarafı Yönlendirici Önbelleği): Kullanıcının tarayıcı belleğinde (in-memory) tutulan önbellektir. `<Link>` bileşenleri ekrana girdiğinde (viewport prefetching) gidilecek sayfanın RSC yükü arka planda önceden indirilir ve geri/ileri tuşlarında sıfır ağ gecikmesiyle anında geçiş sağlanır.

Ayrıca CDN uç noktalarında (V8 Isolates üzerinde) çalışan Edge Middleware (`middleware.ts`) katmanı, istek henüz ana sunucuya ulaşmadan önce milisaniyeler içinde kullanıcının coğrafi konumuna, dil tercihine (`Accept-Language`), çerezlerine veya A/B testi grubuna göre URL yeniden yazma (`NextResponse.rewrite`) işlemini gerçekleştirir. Böylece hem statik CDN hızı korunur hem de kişiselleştirilmiş içerik sunulur.

6. Oluşturma ve Mimari Yaklaşımların Karşılaştırma Tablosu

Aşağıdaki tablo, modern önyüz oluşturma ve ölçekleme stratejilerini performans, SEO ve mühendislik karmaşıklığı açısından karşılaştırmaktadır:

Mimari Yaklaşım TTFB (İlk Bayt Süresi) SEO ve Bot Uyumu İstemci JS Yükü En Uygun Kullanım Senaryosu
Saf CSR (SPA - Vite/React) Çok Hızlı (Statik boş HTML) Zayıf (JS render gerektirir) Çok Yüksek Giriş ekranı arkası SaaS panelleri, B2B yönetim araçları
Geleneksel SSR (Pages Router) Orta-Yavaş (API hızına bağlı) Mükemmel Yüksek (Tam hidrasyon) Kişiselleştirilmiş dinamik sayfalar, haber portalları
SSG + ISR (Statik + Artımlı) Ultra Hızlı (CDN Edge) Mükemmel Düşük-Orta Bloglar, kurumsal siteler, e-ticaret kategori ve ürün sayfaları
RSC + Streaming SSR (App Router) Hızlı (Parçalı akış) Mükemmel Minimum (Yalnızca Client adaları) Yüksek trafikli modern e-ticaret, içerik ve pazar yeri platformları
Mikro-Frontend (Multi-Zones / MF) Stratejiye göre değişir SSR/Zones ile Yüksek Orta (Paylaşımlı paket yönetimi şart) 30+ önyüz geliştiricisi ve birden fazla bağımsız iş birimi olan dev kurumlar

6. Sıkça Sorulan Sorular (SSS)

1. React Server Components (RSC) kullandığımızda `"use client"` bileşenleri sadece tarayıcıda mı çalışır?

Hayır, bu en yaygın yanlış anlaşılmalardan biridir. `"use client"` direktifi ile işaretlenen bileşenler de ilk sayfa isteğinde sunucuda SSR ile HTML'e dönüştürülür, ardından tarayıcıda hidrate edilerek etkileşimli (`useState`, `useEffect`, `onClick`) hale gelir. `"use client"` yalnızca sunucu-istemci sınırını (boundary) çizer.

2. 5 kişilik bir geliştirici ekibimiz var; Mikro-Frontend mimarisine geçmeli miyiz?

Kesinlikle hayır. Mikro-Frontend mimarisi teknik bir performans sorununu değil, organizasyonel ölçeklenme sorununu çözer. 5-15 kişilik ekiplerde bağımsız CI/CD boru hatları, versiyon senkronizasyonu ve paylaşımlı paket yönetimi ciddi bir operasyonel yük yaratır. Bu ölçekte Turborepo veya Nx tabanlı modüler bir Monorepo çok daha verimlidir.

3. Next.js'i kendi sunucumuzda (Self-Hosted Docker/Kubernetes) çalıştırırken ISR ve önbellekleme nasıl yönetilir?

Next.js varsayılan olarak ISR önbelleğini sunucu dosya sisteminde (disk) tutar. Eğer Kubernetes üzerinde birden fazla Next.js kopyası (pod) çalıştırıyorsanız, tüm podların aynı önbelleği görmesi için `next.config.js` içinde özel bir `cacheHandler` tanımlayarak önbelleği Redis'e yönlendirmeniz gerekir.

4. Ada Mimarisi (Islands Architecture - Astro) ile React Server Components arasındaki fark nedir?

Astro'nun öncülük ettiği Ada Mimarisi'nde sayfanın tamamı statik HTML'dir ve etkileşimli bileşenler (adalar) birbirinden bağımsız küçük uygulamalar olarak yüklenir. RSC ise tüm sayfa ağacını tek bir bütünleşik React uygulaması olarak korur; sunucu bileşenleri yeniden çekildiğinde istemci bileşenlerinin yerel durumu (state) kaybolmadan DOM ağacı akıllıca birleştirilir.

5. Mikro-Frontendlerde CSS çakışmalarını (Style Leakage) önlemenin en güvenli yolu nedir?

Küresel CSS sınıflarından kaçınarak CSS Modules, Tailwind CSS (önekli / scoped) veya derleme zamanı atomik CSS çözümleri (StyleX, Vanilla Extract) kullanmaktır. Eğer tamamen farklı çerçeveler aynı sayfada çalışıyorsa Shadow DOM izolasyonu tercih edilmelidir.

Paylaş

Yozel

Codex haberleri en az iki bağımsız kaynakla doğrulanır; düzeltmeler yazının altında tarih ve saatle belirtilir. Yayın ilkelerimiz