Blog/Teknoloji

React Server Components (RSC) Nedir? Kapsamlı Teknik Rehber

Erdi Doğan

Erdi Doğan

Founder & Developer

7 dk okuma
React Server Components (RSC) Nedir? Kapsamlı Teknik Rehber

React Server Components (RSC), React ekosisteminin en önemli paradigma değişikliklerinden biri. Peki neden bu kadar önemli ve SSR'dan farkı ne? Bu yazıda RSC'yi derinlemesine inceliyoruz.

React Server Components Nedir?

React Server Components, component'lerin sunucuda çalışıp, sadece render edilmiş HTML'i (ve bazı metadata'yı) client'a göndermesini sağlayan bir React özelliğidir.

Önemli olan şu: RSC ≠ SSR. Bu ikisi farklı şeyler.

SSR: Component client'ta çalışır, HTML sunucuda oluşturulur
RSC: Component sunucuda çalışır, client'a hiç gönderilmez

Mental Model

Şöyle düşün:

┌─────────────────────────────────────────────────┐
│                    SUNUCU                        │
│  ┌──────────────────────────────────────────┐   │
│  │         Server Components                 │   │
│  │  - Veritabanı sorguları                   │   │
│  │  - API çağrıları                          │   │
│  │  - Dosya okuma                            │   │
│  │  - 0 KB bundle size                       │   │
│  └──────────────────────────────────────────┘   │
└─────────────────────────────────────────────────┘
                      │
                      │ HTML + RSC Payload
                      ▼
┌─────────────────────────────────────────────────┐
│                   CLIENT                         │
│  ┌──────────────────────────────────────────┐   │
│  │         Client Components                 │   │
│  │  - useState, useEffect                    │   │
│  │  - Event handlers (onClick, onChange)     │   │
│  │  - Browser API'leri                       │   │
│  │  - Etkileşimli UI                         │   │
│  └──────────────────────────────────────────┘   │
└─────────────────────────────────────────────────┘

RSC vs SSR: Kritik Fark

Bu iki kavram sıklıkla karıştırılıyor. Aradaki farkı anlamak çok önemli:

Server-Side Rendering (SSR)

// SSR - Component kodu CLIENT'a gönderilir
function ProductPage({ productId }) {
  const [product, setProduct] = useState(null);
  
  useEffect(() => {
    // Client'ta çalışır
    fetch(`/api/products/${productId}`)
      .then(res => res.json())
      .then(setProduct);
  }, [productId]);
  
  return <div>{product?.name}</div>;
}

SSR'da:

  • İlk HTML sunucuda oluşturulur
  • JavaScript bundle client'a gönderilir
  • Hydration ile component interaktif hale gelir
  • Component kodu hem sunucuda hem client'ta çalışır

React Server Components (RSC)

// RSC - Bu kod SADECE sunucuda çalışır
async function ProductPage({ productId }) {
  // Direkt veritabanı sorgusu - client'a gönderilmez!
  const product = await db.products.findUnique({
    where: { id: productId }
  });
  
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      {/* Client component sadece gerekli yerde */}
      <AddToCartButton productId={product.id} />
    </div>
  );
}

RSC'de:

  • Component kodu sadece sunucuda çalışır
  • JavaScript bundle'a dahil edilmez (0 KB)
  • Hydration gerekmez
  • Direkt veritabanı, dosya sistemi erişimi mümkün

Performans Kazanımları

RSC'nin performans etkisi dramatik olabilir:

1. Bundle Size Azalması

// Önceki yaklaşım - Tüm kütüphaneler client'a gider
import { marked } from 'marked';        // +35KB
import { highlight } from 'prism';       // +20KB
import { sanitize } from 'dompurify';    // +15KB

// Toplam: 70KB sadece bu component için
function BlogPost({ content }) {
  const html = sanitize(marked(content));
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
// RSC ile - 0 KB client bundle
async function BlogPost({ slug }) {
  // Bu kütüphaneler sunucuda kalır, client'a gönderilmez
  const { marked } = await import('marked');
  const { highlight } = await import('prism');
  const { sanitize } = await import('dompurify');
  
  const post = await getPost(slug);
  const html = sanitize(marked(post.content));
  
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}

2. Data Fetching Optimizasyonu

// RSC - Paralel veri çekme, waterfall yok
async function Dashboard() {
  // Bu üç sorgu paralel çalışır
  const [user, stats, notifications] = await Promise.all([
    getUser(),
    getStats(),
    getNotifications()
  ]);
  
  return (
    <div>
      <UserProfile user={user} />
      <Stats data={stats} />
      <NotificationList items={notifications} />
    </div>
  );
}

3. Gerçek Dünya Metrikleri

Bizim projelerimizde gözlemlediğimiz sonuçlar:

MetrikSSRRSCİyileşme
JS Bundle245 KB89 KB-64%
LCP2.4s1.1s-54%
TTI3.8s1.6s-58%
INP180ms45ms-75%

Next.js'te RSC Kullanımı

Next.js 13+ App Router ile RSC varsayılan olarak aktif. İşte pratik kullanım:

Server Component (Varsayılan)

// app/products/page.tsx
// 'use client' YOK = Server Component

import { db } from '@/lib/db';

export default async function ProductsPage() {
  // Direkt veritabanı sorgusu
  const products = await db.products.findMany({
    orderBy: { createdAt: 'desc' },
    take: 20
  });
  
  return (
    <main>
      <h1>Ürünlerimiz</h1>
      <ProductGrid products={products} />
    </main>
  );
}

Client Component (Etkileşim Gerektiğinde)

// components/AddToCartButton.tsx
'use client'; // Bu direktif ile client component olur

import { useState } from 'react';
import { addToCart } from '@/actions/cart';

export function AddToCartButton({ productId }: { productId: string }) {
  const [loading, setLoading] = useState(false);
  
  async function handleClick() {
    setLoading(true);
    await addToCart(productId);
    setLoading(false);
  }
  
  return (
    <button 
      onClick={handleClick}
      disabled={loading}
      className="bg-blue-500 text-white px-4 py-2 rounded"
    >
      {loading ? 'Ekleniyor...' : 'Sepete Ekle'}
    </button>
  );
}

Kompozisyon Paterni

// Server Component içinde Client Component
async function ProductCard({ id }) {
  // Sunucuda veri çek
  const product = await getProduct(id);
  
  return (
    <article>
      {/* Statik içerik - Server'da render */}
      <Image src={product.image} alt={product.name} />
      <h2>{product.name}</h2>
      <p>{product.description}</p>
      <span>{formatPrice(product.price)}</span>
      
      {/* Etkileşimli kısım - Client Component */}
      <AddToCartButton productId={id} />
      <WishlistButton productId={id} />
    </article>
  );
}

Ne Zaman Server Component Kullanmalı?

✅ Server Component Kullan

  • Veri çekme (fetch, database query)
  • Backend kaynaklarına erişim (dosya sistemi, environment variables)
  • Hassas bilgiler (API keys, tokens)
  • Büyük bağımlılıklar (markdown parser, syntax highlighter)
  • Statik içerik render

❌ Client Component Kullan

  • Event listeners (onClick, onChange)
  • State ve lifecycle hooks (useState, useEffect)
  • Browser API'leri (localStorage, geolocation)
  • Custom hooks
  • React Class components

Yaygın Hatalar ve Çözümleri

1. Server Component'te useState Kullanmak

// ❌ YANLIŞ - Server Component'te hook kullanılamaz
async function Counter() {
  const [count, setCount] = useState(0); // Error!
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

// ✅ DOĞRU - Client Component olarak işaretle
'use client';
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

2. Client Component'e Server Component Geçmek

// ❌ YANLIŞ - Client component children'da server component
'use client';
function ClientWrapper({ children }) {
  const [open, setOpen] = useState(false);
  return open ? children : null; // Server component burada çalışmaz
}

// ✅ DOĞRU - Composition pattern kullan
// Server component
async function Page() {
  const data = await getData();
  return (
    <ClientWrapper>
      <ServerContent data={data} /> {/* Pre-rendered olarak geçer */}
    </ClientWrapper>
  );
}

3. Gereksiz 'use client' Kullanımı

// ❌ YANLIŞ - Sadece veri gösteriyorsa client olmasına gerek yok
'use client';
function ProductCard({ product }) {
  return (
    <div>
      <h2>{product.name}</h2>
      <p>{product.description}</p>
    </div>
  );
}

// ✅ DOĞRU - Server component olarak bırak
function ProductCard({ product }) {
  return (
    <div>
      <h2>{product.name}</h2>
      <p>{product.description}</p>
    </div>
  );
}

Best Practices

1. Client Boundary'yi Minimize Et

// ❌ Tüm sayfayı client yapmak
'use client';
export default function Page() {
  const [filter, setFilter] = useState('all');
  const products = useProducts(filter);
  
  return (
    <div>
      <Header />
      <FilterBar value={filter} onChange={setFilter} />
      <ProductList products={products} />
      <Footer />
    </div>
  );
}

// ✅ Sadece gerekli kısmı client yapmak
// page.tsx (Server Component)
export default async function Page() {
  const products = await getProducts();
  
  return (
    <div>
      <Header />
      <FilterableProductList products={products} /> {/* Client */}
      <Footer />
    </div>
  );
}

2. Data Fetching'i Yukarı Taşı

// ✅ DOĞRU - Veriyi en üst seviyede çek
async function ProductPage({ params }) {
  const product = await getProduct(params.id);
  const reviews = await getReviews(params.id);
  
  return (
    <>
      <ProductDetails product={product} />
      <ProductReviews reviews={reviews} />
      <AddToCartSection product={product} />
    </>
  );
}

3. Streaming ile Progressive Loading

import { Suspense } from 'react';

export default function Page() {
  return (
    <div>
      {/* Hemen yükle */}
      <Header />
      
      {/* Yavaş veri - stream et */}
      <Suspense fallback={<ProductsSkeleton />}>
        <Products />
      </Suspense>
      
      {/* En yavaş - en son */}
      <Suspense fallback={<RecommendationsSkeleton />}>
        <Recommendations />
      </Suspense>
    </div>
  );
}

Sonuç

React Server Components, frontend geliştirmede köklü bir değişim. SSR'ın evrimleşmiş hali değil, tamamen yeni bir paradigma.

Önemli noktalar:

  • RSC ≠ SSR - Farklı konseptler
  • Varsayılan olarak Server Component kullan
  • Client'ı sadece etkileşim için kullan
  • Bundle size ve performans kazanımları dramatik

Next.js ile RSC kullanmak istiyorsan, Next.js sayfamıza göz at. Detaylı kurulum ve konfigürasyon rehberi orada.


Projenizde React Server Components kullanmak ister misiniz? Bizimle iletişime geçin ve ücretsiz danışmanlık alın.

#React#Server Components#Next.js#Performance#RSC
Paylaş:

Projenizi Hayata Geçirelim

Bu teknolojileri kullanarak projenizi geliştirmek ister misiniz?

Ücretsiz Danışmanlık Alın