Server Component — nima, qanday ishlaydi, qachon ishlatiladi

~20 daq · Next.js · Rendering Strategiyalari

Muammodan boshlaylik

Siz foydalanuvchilar ro'yxatini ko'rsatadigan sahifa yozyapsiz. React da odatdagi usul:

'use client'

export default function UsersPage() {
  const [users, setUsers] = useState([])

  useEffect(() => {
    fetch('/api/users')
      .then(r => r.json())
      .then(setUsers)
  }, [])

  return <ul>{users.map(u => <li>{u.name}</li>)}</ul>
}

Bu ishlaydi. Lekin bir narsaga e'tibor bering — bu kod brauzerda ishlaydi. Ya'ni:

  1. Brauzerga JavaScript yuboriladi (bundle hajmi oshadi)
  2. Sahifa ochiladi — ro'yxat bo'sh
  3. useEffect ishlaydi — /api/users ga so'rov ketadi
  4. Ma'lumot keladi — ro'yxat ko'rinadi

Foydalanuvchi 2 ta so'rovni kutadi: sahifa uchun, ma'lumot uchun. Va /api/users endpoint ni yozish kerak — bu qo'shimcha ish.

Server Component bilan bu muammo yo'q.


Server Component nima

Server Component — serverda ishlaydigan komponent. Brauzerga faqat tayyor HTML yuboriladi, JavaScript yuborilmaydi.

// app/users/page.tsx — Server Component (default)
export default async function UsersPage() {
  // Bu kod serverda ishlaydi — brauzerda emas
  const users = await db.query('SELECT * FROM users')

  return (
    <ul>
      {users.map(u => <li key={u.id}>{u.name}</li>)}
    </ul>
  )
}

Nima o'zgardi:

  • useState, useEffect yo'q — kerak emas
  • /api/users endpoint yo'q — to'g'ridan-to'g'ri DB ga ulanish
  • Brauzerga JavaScript yuborilmaydi — faqat HTML
  • Foydalanuvchi sahifani ochganda ro'yxat darhol ko'rinadi

Serverda ishlash nima beradi

1. Ma'lumotlar bazasiga to'g'ridan-to'g'ri ulanish

// ✅ — bu kod brauzerga chiqmaydi
import { db } from '@/lib/db'

export default async function Page() {
  const products = await db.select().from(productsTable)
  return <ProductList products={products} />
}

Oldin: komponent → /api/products → server → DB. Endi: komponent (serverda) → DB. Bir qadam kamaydi.

2. Maxfiy kalitlar xavfsiz

// ✅ — SECRET_KEY brauzerga hech qachon chiqmaydi
export default async function Page() {
  const data = await fetch('https://api.example.com/data', {
    headers: {
      'Authorization': `Bearer ${process.env.SECRET_KEY}`
    }
  }).then(r => r.json())

  return <div>{data.title}</div>
}

Client Component da process.env.SECRET_KEY ishlatilsa — bu qiymat JavaScript bundle ga tushadi va brauzerda ko'rinadi. Server Component da bu muammo yo'q.

3. Bundle hajmi kichik

Server Component ning JavaScript kodi brauzerga yuborilmaydi. Masalan, markdown render qiluvchi kutubxona — marked, remark — juda katta. Server Component da ishlatilsa brauzerga yuklanmaydi.

// Server Component — 'marked' brauzerga yuklanmaydi
import { marked } from 'marked'  // katta kutubxona

export default async function BlogPost({ params }) {
  const post = await getPost(params.slug)
  const html = marked(post.content)  // serverda render

  return <article dangerouslySetInnerHTML={{ __html: html }} />
}

Server Component da nima ishlamaydi

Server Component da brauzer API lari yo'q. Quyidagilar ishlamaydi:

// ❌ — bular brauzer API, serverda yo'q
useState()
useEffect()
useRef()
onClick, onChange, onSubmit
window, document, localStorage

Agar bular kerak bo'lsa — 'use client' yozasiz.


Server va Client Component birga

Haqiqiy loyihada ikkalasi birga ishlatiladi. Qoida oddiy: Server Component Client Component ni import qila oladi, lekin Client Component Server Component ni import qila olmaydi.

// app/dashboard/page.tsx — Server Component
import { UserStats } from './UserStats'    // Client Component
import { RecentOrders } from './RecentOrders'  // Server Component

export default async function DashboardPage() {
  const stats = await db.getStats()

  return (
    <div>
      <UserStats stats={stats} />      {/* Client — grafik, animatsiya */}
      <RecentOrders />                 {/* Server — DB dan to'g'ridan-to'g'ri */}
    </div>
  )
}
// UserStats.tsx — Client Component (grafik uchun)
'use client'

export function UserStats({ stats }) {
  return <Chart data={stats} />  // brauzerda ishlaydi
}

Ma'lumot serverda olinadi, props orqali Client Component ga uzatiladi. Client Component faqat ko'rsatish uchun javobgar.


Server Component ni qanday tanish

Fayl boshida 'use client' yo'q — Server Component. Fayl boshida 'use client' bor — Client Component.

// Server Component — hech narsa yo'q
export default async function Page() { ... }

// Client Component — 'use client' bor
'use client'
export default function Page() { ... }

App Router da default — Server Component. Siz ataylab 'use client' yozmasangiz — Server Component.


Qachon Server, qachon Client

Ma'lumot olish (DB, API)          → Server Component
Maxfiy kalitlar                   → Server Component
Katta kutubxonalar                → Server Component
SEO muhim kontent                 → Server Component

onClick, onChange                 → Client Component
useState, useEffect               → Client Component
localStorage, window              → Client Component
Real-time yangilanish             → Client Component

Amaliy qoida: avval Server Component yozing. Faqat brauzer API kerak bo'lganda Client Component ga o'ting.


Tez-tez uchraydigan xatolar

1. Server Component da useState ishlatish

// ❌
export default async function Page() {
  const [open, setOpen] = useState(false)
}

Xato: You're importing a component that needs useState. It only works in a Client Component...

// ✅ — 'use client' qo'shing yoki alohida Client Component yarating
'use client'
export default function Page() {
  const [open, setOpen] = useState(false)
}

2. Client Component dan Server Component import qilish

// ❌ — Client Component ichida Server Component bo'lmaydi
'use client'

import { ServerComp } from './ServerComp'  // ishlamaydi

export default function ClientPage() {
  return <ServerComp />
}

Yechim — Server Component ni yuqorida (parent da) render qilib, props orqali uzatish.

3. process.env ni Client Component da ishlatish

// ❌ — SECRET_KEY brauzerda ko'rinadi!
'use client'
export default function Page() {
  const key = process.env.SECRET_KEY  // xavfli!
}

Maxfiy kalitlar faqat Server Component da ishlatiladi.


Xulosa

Server Component — serverda ishlaydigan komponent. Brauzerga faqat HTML yuboriladi.

Nima beradi:

  • DB ga to'g'ridan-to'g'ri ulanish
  • Maxfiy kalitlar xavfsiz
  • Bundle hajmi kichik
  • Sahifa tezroq yuklanadi

Nima ishlamaydi: useState, useEffect, onClick, window, localStorage.

App Router da default — Server Component. 'use client' yozilmasa — Server Component.


Keyingi dars

11-dars: Client Component — "use client", qachon kerak, Server Component dan farqi

Server Component ni tushundik. Endi Client Component ni chuqurroq ko'ramiz — qachon ishlatish kerak, qanday to'g'ri tashkil qilish kerak.