Caching — Request Memoization, Data Cache, Full Route Cache
Muammodan boshlaylik
Next.js bilan ishlaganlarning eng ko'p savollari:
- "Bazada narxni o'zgartirdim, saytda eski narx turibdi!"
- "Build dan keyin sahifa umuman yangilanmayapti"
- "Har so'rovda bazaga murojaat — sayt sekin"
- "
fetchbir xil URL ga 5 marta chaqirildi, lekin so'rov bitta ketdi — nega?"
Javob — Next.js ning bir nechta kesh qatlamlari. Ularni tushunmasdan, xatti-harakat "sehrli" va kutilmagan ko'rinadi.
Hayotiy o'xshatma
Restoran oshxonasi. Bitta buyurtma ichida bir xil sous ikki taomga kerak — bir marta tayyorlanadi (Request Memoization). Tez-tez so'raladigan bulyon — katta qozonda kun bo'yi saqlanadi (Data Cache). Eng mashhur salatlar — oldindan tayyorlab vitrinaga qo'yilgan (Full Route Cache). Mijozning stolida — oldingi taomlar hali turibdi (Router Cache).
To'rt qatlam
| Qatlam | Nima | Qayerda | Qancha |
|---|---|---|---|
| Request Memoization | Bir xil fetch natijasi |
Server, bitta render | Bitta so'rov davomida |
| Data Cache | fetch / unstable_cache natijalari |
Server | So'rovlar va deploy lar orasida |
| Full Route Cache | Tayyor HTML va RSC payload | Server | Build dan keyin, revalidate gacha |
| Router Cache | Ko'rilgan sahifalar RSC payload i | Brauzer | Sessiya davomida |
1. Request Memoization
async function getUser(id: string) {
const res = await fetch(`https://api.dokon.uz/users/${id}`)
return res.json()
}
// layout.tsx, page.tsx, Header.tsx — hammasi getUser('7') ni chaqiradi
Bitta render davomida bir xil URL va opsiyali fetch — bir marta bajariladi. Ma'lumotni "prop drilling" siz har bir komponentda bemalol so'rash mumkin.
fetch emas (Prisma, ORM) — React.cache bilan:
import { cache } from 'react'
export const getUser = cache(async (id: string) => prisma.user.findUnique({ where: { id } }))
2. Data Cache
// keshlanadi — revalidate gacha
await fetch('https://api.dokon.uz/kategoriyalar', { next: { revalidate: 3600 } })
// abadiy (qo'lda revalidate gacha)
await fetch('https://api.dokon.uz/sozlamalar', { cache: 'force-cache' })
// keshlanmaydi
await fetch('https://api.dokon.uz/narxlar', { cache: 'no-store' })
[!INFO] Next.js 15 da
fetchstandart holatda keshlanmaydi (no-store). Next.js 14 da aksincha — standart keshlanardi va bu ko'p chalkashlikka sabab bo'lgan. Endi keshlashni aniq so'rash kerak:cache: 'force-cache'yokinext: { revalidate }.
fetch emas — unstable_cache
import { unstable_cache } from 'next/cache'
export const getKategoriyalar = unstable_cache(
async () => prisma.kategoriya.findMany({ orderBy: { nomi: 'asc' } }),
['kategoriyalar'], // kesh kaliti
{ revalidate: 3600, tags: ['kategoriyalar'] }
)
[!INFO] Next.js ning yangi versiyalarida
unstable_cacheo'rniga'use cache'direktivasi (vacacheTag,cacheLife) taqdim etilgan — funksiya yoki komponentni to'g'ridan-to'g'ri keshlanadigan qilib belgilash. G'oya bir xil: aniq so'ralgan kesh + tag bo'yicha yangilash.
3. Full Route Cache
Build paytida statik sahifalar to'liq render qilinib saqlanadi — so'rov kelganda tayyor HTML beriladi, kod umuman bajarilmaydi.
npm run build
○ / — statik (Full Route Cache)
○ /blog — statik
ƒ /dashboard — dinamik (har so'rovda render)
Sahifa dinamik bo'ladi, agar u ishlatsa:
cookies(),headers(),searchParamscache: 'no-store'fetchexport const dynamic = 'force-dynamic'
Davriy yangilash — ISR
// app/blog/page.tsx
export const revalidate = 600 // 10 daqiqada bir marta qayta render
export default async function Blog() {
const postlar = await prisma.post.findMany({ where: { nashr: true } })
// ...
}
Birinchi so'rov 10 daqiqadan keyin — eski sahifa darhol beriladi, fonda yangisi tayyorlanadi (16-dars, stale-while-revalidate).
4. Router Cache
Brauzerda: <Link> bilan o'tilgan va oldindan yuklangan (prefetch) sahifalar xotirada saqlanadi — "Orqaga" va qayta o'tish bir zumda.
- Server Action dan keyin
revalidatePath/revalidateTag— Router Cache ni ham tozalaydi router.refresh()— joriy sahifani serverdan qayta so'rash
Talab bo'yicha yangilash
Ma'lumot o'zgarganda — kutmasdan, darhol:
'use server'
import { revalidatePath, revalidateTag } from 'next/cache'
export async function narxniYangila(id: string, narx: number) {
await prisma.mahsulot.update({ where: { id }, data: { narx } })
revalidateTag('mahsulotlar') // shu tag li barcha keshlar
revalidatePath(`/mahsulot/${id}`) // aniq sahifa
}
| Funksiya | Nimani yangilaydi |
|---|---|
revalidatePath('/blog') |
Shu yo'l sahifasi |
revalidatePath('/blog', 'layout') |
Shu layout ostidagi barcha sahifalar |
revalidateTag('mahsulotlar') |
tags: ['mahsulotlar'] bilan keshlangan barcha ma'lumotlar |
Tag lar — aniqroq: bitta mahsulot o'zgarganda, unga bog'liq barcha sahifalar (katalog, bosh sahifa, mahsulot sahifasi) bitta chaqiruv bilan.
Tashqi manbadan — CMS webhook
// app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache'
export async function POST(request: Request) {
if (request.headers.get('x-secret') !== process.env.REVALIDATE_SECRET) {
return Response.json({ xato: "Ruxsat yo'q" }, { status: 401 })
}
const { tag } = await request.json()
revalidateTag(tag)
return Response.json({ yangilandi: true })
}
Qaysi biri qachon
| Ma'lumot | Strategiya |
|---|---|
| Deyarli o'zgarmaydi (sahifalar, kategoriyalar) | Statik + revalidateTag o'zgarganda |
| Vaqti-vaqti bilan (blog, katalog) | revalidate = 600 + talab bo'yicha |
| Har doim yangi (narx, qoldiq, savat) | Dinamik, no-store |
| Foydalanuvchiga xos (profil, buyurtmalar) | Dinamik (cookies) — hech qachon umumiy keshda emas |
[!WARNING] Foydalanuvchiga xos ma'lumotni
unstable_cacheyokiforce-cachebilan umumiy kalit ostida keshlamang — bir foydalanuvchining ma'lumoti boshqasiga ko'rinib qoladi. Kesh kalitigauserIdqo'shing yoki bunday ma'lumotni keshlamang.
Tez-tez uchraydigan xatolar
1. "Production da yangilanmayapti"
Development da har so'rov qayta render bo'ladi, production da sahifa statik. revalidate yoki revalidatePath/Tag.
2. Server Action dan keyin revalidate yo'q
Bazada o'zgardi, sahifa eski.
3. Hamma narsani force-dynamic
Sayt ishlaydi, lekin har so'rov — to'liq render va baza so'rovi; kesh foydasi yo'qoladi.
Xulosa
Request Memoization — bitta render da bir xil fetch bir marta; ORM uchun React.cache
Data Cache — fetch { cache: 'force-cache' | 'no-store', next: { revalidate, tags } }
— unstable_cache / 'use cache' — ORM natijalari
Next.js 15 — fetch standart holatda keshlanmaydi
Full Route Cache — statik sahifalar; cookies/headers/searchParams → dinamik
revalidate = N — ISR; revalidatePath / revalidateTag — darhol
Router Cache — brauzerda; router.refresh()
Foydalanuvchiga xos ma'lumot — umumiy keshda emas
Keyingi dars
60-dars: Edge Runtime — nima, Node.js dan farqi, qachon kerak
Foydalanuvchiga yaqin joyda ishlaydigan yengil runtime va uning cheklovlari.