Dynamic Rendering — har so'rovda generatsiya, qachon mos

~15 daq · Next.js · Rendering Strategiyalari

Muammodan boshlaylik

Siz bank ilovasining dashboard sahifasini yozyapsiz. Foydalanuvchi kirganda o'z balansini, so'nggi tranzaksiyalarini ko'radi.

Static Rendering ishlatib bo'lmaydi — har bir foydalanuvchi uchun boshqacha ma'lumot. Jasurning balansi Malikaning balansidan farq qiladi. Build vaqtida bu ma'lumotlarni oldindan yaratib bo'lmaydi.

Bunday sahifalar uchun Dynamic Rendering kerak — har bir so'rovda server qayta render qiladi.


Dynamic Rendering qanday ishlaydi

Jasur dashboard ga kiradi
      ↓
Server Jasurning tokenini o'qiydi
      ↓
DB dan Jasurning ma'lumotlarini oladi
      ↓
HTML render qiladi
      ↓
Jasurga yuboradi

Malika dashboard ga kiradi
      ↓
Server Malikaning tokenini o'qiydi
      ↓
DB dan Malikaning ma'lumotlarini oladi
      ↓
HTML render qiladi
      ↓
Malikaga yuboradi

Har so'rovda server ishlaydi. Har foydalanuvchi o'z ma'lumotini ko'radi.


Qanday yoqiladi

Dynamic Rendering ni qo'lda yoqish shart emas — Next.js avtomatik aniqlaydi. Sahifada quyidagilardan biri bo'lsa — Dynamic Rendering yoqiladi:

1. cookies() — foydalanuvchiga xos ma'lumot

import { cookies } from 'next/headers'

export default async function Dashboard() {
  const cookieStore = await cookies()
  const token = cookieStore.get('auth-token')?.value

  const user = await getUserByToken(token)

  return <h1>Salom, {user.name}</h1>
}

Cookie har foydalanuvchi uchun boshqacha — sahifa statik bo'la olmaydi.

2. headers() — so'rov sarlavhalari

import { headers } from 'next/headers'

export default async function Page() {
  const headersList = await headers()
  const userAgent = headersList.get('user-agent')
  const country = headersList.get('x-country')  // CDN dan

  return <p>Siz {country} dan kiryapsiz</p>
}

3. cache: 'no-store' — keshlanmasin

export default async function StockPage() {
  // Har so'rovda yangi narx
  const prices = await fetch('https://api.example.com/prices', {
    cache: 'no-store'
  }).then(r => r.json())

  return <PriceTable prices={prices} />
}

4. searchParams — URL parametrlari

export default async function SearchPage({
  searchParams,
}: {
  searchParams: { q?: string; page?: string }
}) {
  const { q, page } = await searchParams
  const results = await search(q, page)

  return <SearchResults results={results} />
}

?q=javascript&page=2 — har foydalanuvchi boshqacha qidiruv qiladi.


dynamic export — majburiy Dynamic

Ba'zan sahifada yuqoridagi belgilar yo'q, lekin siz uni majburiy Dynamic qilmoqchisiz. Buning uchun:

export const dynamic = 'force-dynamic'

export default async function Page() {
  const data = await fetch('/api/data').then(r => r.json())
  return <div>{data.title}</div>
}

force-dynamic — sahifa har doim Dynamic Rendering bilan ishlaydi, hatto fetch keshlanishi mumkin bo'lsa ham.

Aksincha — majburiy Static:

export const dynamic = 'force-static'

Amaliy misol — foydalanuvchi dashboard

// app/dashboard/page.tsx
import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'

export default async function DashboardPage() {
  const cookieStore = await cookies()
  const token = cookieStore.get('auth-token')?.value

  // Token yo'q — login sahifasiga yo'naltirish
  if (!token) redirect('/login')

  const user = await db.getUserByToken(token)
  const stats = await db.getUserStats(user.id)

  return (
    <div>
      <h1>Salom, {user.name}</h1>
      <div>
        <p>Balans: {stats.balance} so'm</p>
        <p>Buyurtmalar: {stats.orders}</p>
      </div>
    </div>
  )
}

cookies() ishlatilgani uchun Next.js bu sahifani avtomatik Dynamic deb belgilaydi. Har so'rovda server tokenni o'qiydi, foydalanuvchini topadi, uning ma'lumotlarini qaytaradi.


Static vs Dynamic — qachon qaysinisi

                    Static          Dynamic
────────────────────────────────────────────
Blog post           ✅              —
Hujjatlar           ✅              —
Marketing sahifa    ✅              —
Foydalanuvchi profil —             ✅
Dashboard           —              ✅
Qidiruv natijalari  —              ✅
Buyurtma holati     —              ✅
Narxlar (real-time) —              ✅

Oddiy qoida: ma'lumot foydalanuvchiga xos yoki real-time bo'lsa — Dynamic.


Dynamic Rendering ning kamchiligi

Dynamic Rendering ning bir kamchiligi bor — har so'rovda server ishlaydi. Ko'p trafik bo'lsa server yuki oshadi, javob vaqti uzayadi.

Yechim — Streaming. Sahifaning bir qismini darhol yuborish, qolganini asta-sekin. Foydalanuvchi hamma narsa yuklanishini kutmaydi.

Bu — keyingi darsning mavzusi.


Tez-tez uchraydigan xatolar

1. Dynamic sahifani Static deb o'ylash

// Bu sahifa Dynamic — lekin siz Static deb o'ylaysiz
export default async function Page({ searchParams }) {
  const q = searchParams.q  // searchParams → Dynamic!
  const results = await search(q)
  return <div>{results}</div>
}

searchParams ishlatilganda sahifa avtomatik Dynamic bo'ladi. Build natijasida ƒ belgisini ko'rasiz.

2. cookies() ni await qilmaslik (Next.js 15+)

// ❌
import { cookies } from 'next/headers'

export default async function Page() {
  const cookieStore = cookies()  // xato! await kerak
  const token = cookieStore.get('token')
}

// ✅
export default async function Page() {
  const cookieStore = await cookies()
  const token = cookieStore.get('token')
}

3. Har sahifani Dynamic qilish

// ❌ — statik sahifaga ham force-dynamic qo'yish
export const dynamic = 'force-dynamic'

export default function AboutPage() {
  return <h1>Biz haqimizda</h1>  // bu statik bo'lishi kerak edi
}

force-dynamic faqat haqiqatan dinamik bo'lishi kerak sahifalarga.


Xulosa

Dynamic Rendering — har so'rovda server render qiladi. Foydalanuvchiga xos yoki real-time ma'lumotlar uchun.

Avtomatik yoqiladi:

cookies()          → foydalanuvchiga xos
headers()          → so'rov sarlavhalari
cache: 'no-store'  → keshlanmasin
searchParams       → URL parametrlari

Qo'lda yoqish: export const dynamic = 'force-dynamic'

Kamchiligi — har so'rovda server ishlaydi. Ko'p trafik bo'lsa — Streaming bilan birga ishlatish yaxshiroq.


Keyingi dars

15-dars: Streaming — Suspense bilan, foydalanuvchi tajribasini yaxshilash

Dynamic Rendering da sahifa to'liq tayyor bo'lguncha foydalanuvchi kutadi. Streaming bu muammoni hal qiladi — kontent bo'laklarga bo'linib yuboriladi.