# Üretimde React Server Components: desenler ve tuzaklar
> Üretimde React Server Components: savaşta sınanmış desenler, sık karşılaşılan anti-desenler ve sağlam Next.js 15 uygulamaları için hata ayıklama stratejileri.
- Published: 2026-03-29
- Updated: 2026-05-04
- Author: Anthony Fillion-Maillet
- Tags: react server components, next.js 15, rsc patterns, production, react 19
- Reading time: 9 min
---
React Server Components (RSC), Next.js 15'te sunucu tarafı render'ın işleyişini temelden değiştirir; ancak üretim ortamındaki kullanım, resmi dokümantasyonun her zaman ele almadığı tuzakları ortaya çıkarır. Bu makale, çalışan desenleri, kırılan desenleri ve sorunların üretime ulaşmadan önce nasıl teşhis edileceğini ele alır.
> **Server Components ve Client Components**
>
> Bir Server Component yalnızca sunucuda çalışır ve tarayıcıya sıfır JavaScript gönderir. Bir Client Component (`"use client"` ile işaretlenmiş) her iki tarafta da çalışır. Kural: Client Components'i mümkün olduğunca küçük ve ağacın mümkün olduğunca alt seviyesinde tutmak.
## Sunucu-istemci sınırı: boundary desenini anlamak
En yaygın RSC tuzağı, Server ve Client Components arasındaki sınırla ilgilidir. Bir bileşen `"use client"` direktifini taşıdığında, **içe aktarılan tüm çocukları da Client Component haline gelir**, direktif olmasa bile.
```tsx
// ProductPage.tsx (Server Component)
import { ProductDetails } from './ProductDetails'
import { AddToCartButton } from './AddToCartButton'
export default async function ProductPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const product = await getProduct(id)
return (
{/* Server Component: doğrudan DB erişimi */}
{/* Client Component: izole etkileşim */}
)
}
```
```tsx
// AddToCartButton.tsx (Client Component)
'use client'
import { useState } from 'react'
export function AddToCartButton({ productId, price }: { productId: string; price: number }) {
const [adding, setAdding] = useState(false)
async function handleAdd() {
setAdding(true)
await fetch('/api/cart', {
method: 'POST',
body: JSON.stringify({ productId, quantity: 1 }),
})
setAdding(false)
}
return (
)
}
```
Anahtar desen: verileri Server Component'tan Client Component'a **serileştirilebilir prop'lar** olarak geçirmek. Fonksiyonlar, sınıflar ve Date nesneleri bu sınırı geçemez.
## Anti-desen: gereksiz Client Component sarmalayıcısı
Sık yapılan bir hata, Server Component çocuklarını saran bir Client Component oluşturmak ve böylece tüm alt ağacı istemci tarafına zorlamaktır.
```tsx
// PageWrapper.tsx — ANTİ-DESEN
'use client'
import { useState } from 'react'
// Tüm çocuk içerik istemci tarafına geçer
export function PageWrapper({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState('light')
return (
{children}
)
}
```
> **slot olarak children**
>
> Çözüm: Server Components'i `children` olarak geçirmek (slot deseni). Prop olarak geçirilen çocuklar, ebeveyn bir Client Component olsa bile Server Components olarak kalır. Yukarıdaki kod, `children` bir Server Component ebeveynden geldiği sürece doğru şekilde çalışır.
```tsx
// layout.tsx (Server Component)
import { PageWrapper } from './PageWrapper'
import { HeavyServerContent } from './HeavyServerContent'
export default function Layout() {
return (
{/* İstemci sarmalayıcısına rağmen Server Component olarak kalır */}
)
}
```
Bu kompozisyon deseni, ağır içerik için sunucu render'ının faydalarını korurken sarmalayıcı seviyesinde etkileşimi mümkün kılar.
## Asenkron veri işleme: bileşende fetch deseni
React 19 ve Next.js 15, Server Components içinde doğrudan `async/await` desteği sunar. Bu desen, eski `getServerSideProps` yaklaşımına kıyasla veri çekmeyi basitleştirir.
```tsx
// UserProfile.tsx (Server Component)
import { cache } from 'react'
// Aynı render içindeki özdeş çağrıları tekilleştirir
const getUser = cache(async (userId: string) => {
const res = await fetch(`https://api.example.com/users/${userId}`, {
next: { revalidate: 3600 }, // 1 saat cache
})
if (!res.ok) throw new Error('User not found')
return res.json()
})
export default async function UserProfile({ userId }: { userId: string }) {
const user = await getUser(userId)
return (
)
}
```
Üç kritik nokta:
- React'in `cache()` fonksiyonu, tek bir sunucu render'ı sırasında özdeş çağrıları tekilleştirir
- `next: { revalidate }`, Next.js tarafında cache süresini kontrol eder
- Asenkron bir Server Component'taki hatalar en yakın `error.tsx`'i tetikler
## Serileştirme tuzağı: sınırı geçemeyenler
Server ve Client Components arasında değişen verilerin JSON ile serileştirilebilir olması gerekir. Sessiz hatalara veya çökmelere yol açan durumlar şunlardır.
```tsx
// TUZAK: serileştirilemez tipleri geçirmek
// Fonksiyon — çalışmaz
{ /* server action */ }} />
// Bunun yerine içe aktarılmış bir Server Action kullanmak
import { submitForm } from '@/lib/actions/form'
// Date nesnesi — çalışmaz
// ISO string — çalışır
// Map, Set, RegExp — çalışmaz
// Düz nesne veya dizi — çalışır
```
Server Actions (`"use server"` ile işaretli fonksiyonlar) istisnadır: Next.js bunları HTTP endpoint'lerine dönüştürdüğü için bir Client Component'a prop olarak geçirilebilirler.
## Streaming ve Suspense: ilerlemeli yükleme desenleri
Suspense ile SSR streaming, HTML'i tarayıcıya ilerlemeli olarak gönderir. Optimal desen, her asenkron bölümün etrafında granüler Suspense sınırları kullanır.
```tsx
// DashboardPage.tsx (Server Component)
import { Suspense } from 'react'
import { RevenueChart } from './RevenueChart'
import { RecentOrders } from './RecentOrders'
import { UserStats } from './UserStats'
export default function DashboardPage() {
return (
}>
}>
}>
)
}
```
Her bölüm bağımsız olarak yüklenir. `RevenueChart` 3 saniye, `UserStats` 200 ms sürerse, istatistikler grafiği beklemeden anında görünür.
> **Suspense ve SEO**
>
> Bir Suspense sınırı içindeki içerik sunucuda render edilir ve ilk HTML'e dahil edilir. Crawler'lar tam içeriği görür. Streaming yalnızca tarayıcıya teslim hızını etkiler, SEO görünürlüğünü değil.
## Üretimde hata ayıklama: RSC sorunlarını izleme
RSC hataları çoğu zaman karmaşıktır. Üç teşhis tekniği üretimde işe yarar.
**1. Hidrasyon uyumsuzluklarını tespit etmek**
```tsx
// debug-hydration.tsx
'use client'
import { useEffect, useState } from 'react'
export function HydrationDebug() {
const [isClient, setIsClient] = useState(false)
useEffect(() => {
setIsClient(true)
}, [])
if (process.env.NODE_ENV !== 'development') return null
return (
{isClient ? 'Client' : 'Server'}
)
}
```
**2. RSC payload'ını loglamak**
Next.js 15'te `next.config.ts` içinde RSC log'larını etkinleştirmek:
```typescript
// next.config.ts
const nextConfig = {
logging: {
fetches: {
fullUrl: true, // Tam fetch URL'lerini gösterir
},
},
}
export default nextConfig
```
**3. Payload boyutunu kontrol etmek**
Aşırı büyük bir RSC payload'ı (> 128 KB) performansı düşürür. DevTools'ta `text/x-component` content type'lı ağ isteklerini izlemek gerekir.
## İleri desen: Server Actions ile kompozisyon
Server Actions ve Server Components birleşimi doğal bir CQRS deseni oluşturur: sunucuda okumalar (RSC), action'lar üzerinden yazmalar.
```tsx
// TodoList.tsx (Server Component)
import { getTodos } from '@/lib/services/todo'
import { TodoForm } from './TodoForm'
import { deleteTodo } from '@/lib/actions/todo'
export default async function TodoList() {
const todos = await getTodos()
return (
{todos.map(todo => (
{todo.title}
))}
)
}
```
```tsx
// actions/todo.ts
'use server'
import { revalidatePath } from 'next/cache'
import { TodoService } from '@/lib/services/todo'
export async function deleteTodo(formData: FormData) {
const id = formData.get('id') as string
await TodoService.delete(id)
revalidatePath('/todos')
}
```
`revalidatePath` çağrısı, tam sayfa yenilemesi olmadan güncellenmiş verilerle yeni bir Server Component render'ını tetikler.
Bu konularda daha derin mülakat hazırlığı için SharpSkill'deki [Next.js Server Actions](/technologies/react-next/interview-questions/nextjs-server-actions) modülü ile [Next.js Data Fetching](/technologies/react-next/interview-questions/nextjs-data-fetching) modülünü incelemek faydalıdır. [Resmi React dokümantasyonu](https://react.dev/reference/rsc/server-components) Server Components spesifikasyonunun tamamını ele alır.
## Sonuç
- Client Components'i bileşen ağacının altında küçük ve izole tutmak
- Bir istemci sarmalayıcısı içinde Server Components'i korumak için slot desenini (`children`) kullanmak
- Sunucu-istemci sınırını geçen prop'ların serileştirilebilirliğini her zaman doğrulamak
- Her bağımsız asenkron bölümün etrafına granüler Suspense sınırları yerleştirmek
- Üretimde RSC payload boyutunu izlemek (hedef < 128 KB)
- Doğal bir CQRS deseni için Server Components (okumalar) ve Server Actions (yazmalar) birleşimini kullanmak
- Tek bir sunucu render'ı içindeki istekleri tekilleştirmek için React'in `cache()` fonksiyonunu kullanmak
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/tr/blog/react-next/react-server-components-patterns-pitfalls