13.7-bob: Caching va Performance
13-QISM — Next.js · 7-mavzu
1. Kirish va motivatsiya
Next.js'ning eng katta kuchi — tezlik. Lekin bu tezlik tasodifan emas: u ortida caching (keshlash — ma'lumot yoki natijani saqlab, qayta ishlatish) qatlamlari turibdi. Bu — Next.js'ning eng murakkab, eng ko'p chalkashtiriladigan, lekin eng muhim mavzularidan biri. Oldingi boblarda biz keshni qisman ko'rganmiz (13.4 fetch kesh, 13.5 request memoization), lekin endi to'liq rasmni ko'ramiz: Next.js'da to'rt xil kesh qatlami bor, ular birga ishlaydi, va ularni tushunmasdan "nega ma'lumotim eskirgan?" yoki "nega o'zgarishim ko'rinmayapti?" degan savollarga javob topib bo'lmaydi.
Ikkinchi yarmida — performance optimizatsiyasi: Next.js ilovangizni yanada tezroq qilishning amaliy vositalari. Rasm — har saytning eng og'ir qismi (rasm — next/image bilan avtomatik optimizatsiya: o'lcham, format, lazy load). Shrift — next/font bilan (layout shift'siz, tez). Skript — next/script bilan (to'g'ri yuklash). Va katta komponentlarni faqat kerak bo'lganda yuklash (next/dynamic — lazy loading). Bularning hammasi Core Web Vitals (Google'ning tezlik o'lchovlari — LCP, CLS, INP)ni yaxshilaydi, bu esa SEO va foydalanuvchi tajribasiga to'g'ridan ta'sir qiladi.
Bu bob: to'rt kesh qatlami (Request Memoization, Data Cache, Full Route Cache, Router Cache — chuqur), ular qanday ishlaydi (birga), keshni boshqarish (revalidate, tags, no-store), revalidatePath/Tag (on-demand), rasm optimizatsiyasi (next/image), shrift (next/font), skript (next/script), lazy loading (next/dynamic), bundle tahlili, Core Web Vitals (LCP/CLS/INP), va prefetching. Har mavzu to'liq, har kod misolida maqsad + izoh + "nima qiladi" bilan ochib beriladi.
O'xshatish: Next.js caching — bu kutubxonadagi kitoblar tizimi. Har safar kitob kerak bo'lganda uni bosmaxonadan qayta buyurtma qilish (har so'rovda DB/API'dan ma'lumot) — sekin va isrof. Buning o'rniga kutubxonada bir necha qatlam bor: (1) o'qish stolingizdagi kitoblar (Request Memoization — joriy ish davomida qo'l ostida — bir render); (2) kutubxona javonlari (Data Cache — ko'p marta ishlatiladigan kitoblar saqlangan — fetch kesh); (3) tayyor nusxalar (Full Route Cache — eng mashhur kitoblar oldindan nusxalangan — statik sahifa); (4) uyingizdagi shaxsiy javon (Router Cache — yaqinda o'qigan kitoblar uyda — client navigatsiya). Har qatlam tezroq, lekin "eskirish" muammosi bor (kitob yangi nashr chiqsa — eski nusxani yangilash kerak — revalidate). Performance optimizatsiyasi esa — kutubxonani samarali tashkil qilish (kitoblar yengil —
next/image; tez topiladigan — prefetch; faqat kerakli — lazy load).
Nega muhim?
- Tezlik manbasi — Next.js'ning tezligi kesh qatlamlariga asoslangan (tushunmasdan optimallashtirib bo'lmaydi).
- "Eskirgan ma'lumot" muammosi — keshni tushunmaslik eng keng Next.js chalkashligi (o'zgardi, lekin ko'rinmaydi).
- SEO va konversiya — tez sayt (Core Web Vitals) Google'da yuqori, foydalanuvchi qoladi (sekin sayt — ketadi).
- Professional sifat — rasm/shrift/bundle optimizatsiyasi — professional ilova belgisi.
2. Nazariya — chuqur tushuntirish
2.1. To'rt kesh qatlami (umumiy)
NEXT.JS — 4 KESH QATLAMI (server va client'da — birga ishlaydi):
┌──────────────────────┬─────────┬──────────────┬─────────────────────┐
│ Kesh │ Qayerda │ Nima saqlaydi│ Davomiyligi │
├──────────────────────┼─────────┼──────────────┼─────────────────────┤
│ 1. Request Memoization│ server │ fetch natija │ BIR render (so'rov) │
│ 2. Data Cache │ server │ fetch natija │ DOIMIY (revalidate'gacha)│
│ 3. Full Route Cache │ server │ sahifa HTML │ build/revalidate │
│ 4. Router Cache │ client │ sahifa RSC │ sessiya (qisqa) │
└──────────────────────┴─────────┴──────────────┴─────────────────────┘
OQIM (so'rov kelganda — qaysi kesh qachon):
Brauzep [4. Router Cache] server [3. Full Route Cache]
[2. Data Cache] [1. Memoization] DB/API
4 qatlam: Memoization (1 render), Data (doimiy fetch), Full Route (HTML), Router (client)
Har qatlam tezroq qiladi, lekin "eskirish" — revalidate bilan boshqariladi (2.6)To'rt kesh qatlami — Next.js caching'ning to'liq rasmi. Next.js'da to'rt xil kesh bor (server va client'da), har biri turli narsani, turli muddatga saqlaydi: (1) Request Memoization (server) — bir render (so'rov) davomida bir xil
fetchni dedup qiladi (13.5: 2.3 — bir render'da bir xil so'rov bir marta); (2) Data Cache (server) —fetchnatijasini doimiy saqlaydi (so'rovlar va deploylar orasida — revalidate'gacha — 13.4: 2.7); (3) Full Route Cache (server) — statik sahifa HTMLini saqlaydi (build paytida — 13.4: 2.4 SSG); (4) Router Cache (client — brauzer) — tashrif buyurilgan sahifalar RSC (React Server Component) natijasini brauzer'da saqlaydi (client navigatsiya tez bo'lishi uchun). Oqim (so'rov kelganda): brauzer avval Router Cache'ni (client) tekshiradi, keyin server'da Full Route Cache (HTML), keyin Data Cache (fetch), keyin Memoization, oxirida DB/API. Ya'ni har qatlam — "qisqa yo'l" (agar keshda bo'lsa, keyingi qatlamga bormaydi — tezroq). Ikki nuqta: (1) 4 qatlam — Memoization (1 render), Data (doimiy fetch), Full Route (HTML), Router (client) — har biri turli darajada; (2) har qatlam tezroq qiladi, lekin "eskirish" muammosi bor (kesh eski ma'lumotni saqlab qolishi mumkin — revalidate bilan boshqariladi — 2.6). Bu to'rt qatlamni tushunish — Next.js performance va "nega eskirgan?" muammosining kaliti.
2.2. Request Memoization (1-qatlam)
REQUEST MEMOIZATION — BIR render'da bir xil fetch BIR marta (13.5: 2.3 — qisqa):
// Bir render davomida (bir so'rov):
async function getUser() { return fetch("/api/user").then(r => r.json()); }
// Layout: await getUser() ┐
// Page: await getUser() ├─ 3 chaqiruv, lekin TARMOQqa 1 marta (memoize)
// Navbar: await getUser() ┘
XUSUSIYATLARI:
- Faqat BIR render davomida (so'rov tugasa — yo'qoladi)
- Faqat GET fetch (bir xil URL + opsiya)
- AVTOMATIK (React fetch'ni o'rab — sozlash kerak emas)
- DB so'rov uchun — React cache() (13.5: Misol 9)
Request Memoization — bir render'da dedup (props drilling'siz — har komponent o'zi chaqiradi)
Faqat bir render (qisqa); doimiy kesh — Data Cache (2.3)Request Memoization (1-qatlam) — eng qisqa muddatli kesh (13.5: 2.3 — qisqa takror). Request Memoization — bir render (bir so'rov) davomida bir xil
fetchni bir marta bajarish (dedup). Misol:getUser()ni Layout, Page, Navbar — uchalasi chaqirsa ham — tarmoqqa bir marta boradi (qolgani xotiradan — 13.5: 2.3). Xususiyatlari: (1) faqat bir render davomida (so'rov tugasa — kesh yo'qoladi — eng qisqa); (2) faqat GETfetch(bir xil URL + opsiya); (3) avtomatik (Reactfetchni o'rab keshlaydi — sozlash kerak emas); (4) DB so'rov uchun — Reactcache()(fetchemas — 13.5: Misol 9 — qo'lda o'rab). Maqsadi: props drilling'ni yo'qotish (12.1: 2.1) — har komponent o'ziga kerak ma'lumotni mustaqil chaqiraversin (getUser()), takror bo'lmaydi (dedup). Ikki nuqta: (1) Request Memoization — bir render'da dedup (props drilling'siz — toza arxitektura); (2) faqat bir render (qisqa muddatli) — doimiy kesh esa Data Cache (2.3 — keyingi qatlam). Bu — to'rt qatlamning eng qisqasi (bir render), lekin eng tez-tez ishlaydigani (har render'da). Bu qatlamni tushunish Server Components arxitekturasini (har komponent o'z ma'lumotini) toza qiladi.
2.3. Data Cache (2-qatlam)
DATA CACHE — fetch natijasini DOIMIY saqlaydi (so'rovlar/deploylar orasida):
// fetch — Data Cache'da saqlanadi (opsiyaga qarab):
fetch(url, { cache: "force-cache" }) // doimiy kesh (Data Cache'da)
fetch(url, { next: { revalidate: 3600 } }) // 1 soat kesh (keyin yangila)
fetch(url, { cache: "no-store" }) // Data Cache'ga YOZILMAYDI (har so'rov yangi)
XUSUSIYATLARI:
- DOIMIY (Request Memoization'dan farqli — render tugasa ham qoladi)
- So'rovlar orasida (foydalanuvchi A oldi kesh foydalanuvchi B keshdan — tez)
- Deploylar orasida ham (build'dan keyin ham qoladi — agar revalidate bo'lmasa)
- revalidate yoki tag bilan boshqariladi 2.6-bob
┌────────────────────────────────────────────────────────────┐
│ Data Cache: fetch natija DOIMIY (so'rovlar/deploylar aro) │
│ bir foydalanuvchi olsa, keyingilar keshdan (tez, kam DB) │
└────────────────────────────────────────────────────────────┘
Data Cache — fetch natija DOIMIY (so'rovlar aro — DB/API yuki kamayadi)
Next.js 15: default keshlamaydi (force-cache yoki revalidate kerak — 13.4: 2.7)Data Cache (2-qatlam) — eng muhim, doimiy kesh. Data Cache —
fetchnatijasini doimiy saqlaydi (Request Memoization'dan farqli — render tugasa ham qoladi, so'rovlar va hatto deploylar orasida).fetchopsiyalari bilan boshqariladi:cache: "force-cache"(doimiy kesh — Data Cache'da),next: { revalidate: 3600 }(1 soat kesh, keyin yangila — ISR — 13.4: 2.5),cache: "no-store"(Data Cache'ga yozilmaydi — har so'rov yangi — dinamik). Xususiyatlari: (1) doimiy (render tugagach ham qoladi — Memoization'dan uzunroq); (2) so'rovlar orasida (foydalanuvchi A ma'lumotni olsa — keshga tushadi — foydalanuvchi B keshdan oladi — tez, DB/API'ga yuk kamayadi); (3) deploylar orasida ham (yangi build'dan keyin ham qoladi — agar revalidate bo'lmasa); (4) revalidate yoki tag bilan boshqariladi 2.6-bob. Maqsadi: DB/API yukini kamaytirish (bir marta olingan ma'lumot ko'p marta ishlatiladi — masalan mahsulot ro'yxati — 1000 foydalanuvchi uchun 1 marta DB so'rovi). Ikki nuqta: (1) Data Cache — fetch natija doimiy (so'rovlar aro — DB/API yuki keskin kamayadi — server tez, arzon); (2) Next.js 15: default keshlamaydi (force-cacheyokirevalidatekerak — 13.4: 2.7 — 14'dan farq). Bu — Next.js'ning eng muhim kesh qatlami (ma'lumot tezligining asosi). Data Cache — "bir marta ol, ko'p marta ber" tamoyili.
2.4. Full Route Cache (3-qatlam)
FULL ROUTE CACHE — STATIK sahifa HTML'ini saqlaydi (build paytida — SSG):
STATIK sahifa (13.4: 2.4) HTML build paytida generatsiya Full Route Cache'da:
// app/blog/page.tsx (statik) HTML bir marta build'da har so'rov keshdan (tez)
XUSUSIYATLARI:
- Faqat STATIK sahifa (dinamik — SSR — keshlanmaydi — 13.4: 2.6)
- Sahifa butun HTML + RSC payload saqlanadi
- Build paytida (yoki ISR revalidate'da) generatsiya
- revalidatePath/Tag yoki yangi deploy bilan yangilanadi
STATIK vs DINAMIK (Full Route Cache'ga ta'sir):
Statik (cookies/no-store yo'q) Full Route Cache'da (tez)
Dinamik (cookies/no-store) Full Route Cache YO'Q (har so'rov render)
Full Route Cache — statik sahifa HTML (build'da — har so'rov tayyor HTML — eng tez)
Faqat statik sahifa; dinamik (SSR) keshlanmaydi (13.4: 2.6 — har so'rov render)Full Route Cache (3-qatlam) — statik sahifa HTML keshi. Full Route Cache — statik sahifaning to'liq HTMLini (va RSC payload'ini) saqlaydi (build paytida generatsiya — 13.4: 2.4 SSG'ning kesh tomoni). Misol:
app/blog/page.tsxstatik bo'lsa, uning HTML'i build paytida bir marta generatsiya qilinadi va Full Route Cache'da saqlanadi — har so'rov tayyor HTMLni keshdan oladi (server render yo'q — eng tez). Xususiyatlari: (1) faqat statik sahifa (dinamik — SSR — Full Route Cache'ga tushmaydi — har so'rov render — 13.4: 2.6); (2) sahifa butun HTML + RSC payload saqlanadi; (3) build paytida (yoki ISR revalidate'da) generatsiya; (4)revalidatePath/revalidateTagyoki yangi deploy bilan yangilanadi. Statik vs dinamik (Full Route Cache'ga ta'sir): statik (cookies/no-store yo'q — 13.4: 2.6) Full Route Cache'da (tez); dinamik (cookies/no-store) Full Route Cache yo'q (har so'rov render). Ikki nuqta: (1) Full Route Cache — statik sahifa HTML (build'da generatsiya — har so'rov tayyor HTML — eng tez, hatto CDN'dan); (2) faqat statik sahifa (dinamik SSR keshlanmaydi — har so'rov render — 13.4: 2.6). Bu — Data Cache (ma'lumot) ustidagi qatlam (butun sahifa HTML — render natijasi). Full Route Cache — SSG tezligining 13.4-bob ichki mexanizmi (sahifa bir marta render, ko'p marta beriladi). Bu qatlam Data Cache bilan birga ishlaydi (sahifa statik bo'lsa, ham HTML, ham ma'lumot keshda).
2.5. Router Cache (4-qatlam, client)
ROUTER CACHE — BRAUZER'da tashrif buyurilgan sahifani saqlaydi (client navigatsiya tez):
foydalanuvchi /products /about /products (qaytsa):
1-marta /products: server'dan (RSC payload)
/products'ga QAYTGANda: ROUTER CACHE'dan (brauzer — server'ga BORMAYDI — darrov!)
XUSUSIYATLARI:
- CLIENT'da (brauzer xotirasida — sessiya davomida)
- <Link> prefetch bilan to'ldiriladi (2.10 — havola ko'rinsa oldindan yuklaydi)
- Tez navigatsiya (qaytgan sahifa darrov — server'ga so'rov yo'q)
- router.refresh() yoki revalidate bilan tozalanadi
TUZOQ: mutation'dan keyin Router Cache eski ko'rsatishi mumkin:
Server Action'da revalidatePath Router Cache ham yangilanadi (13.5: 2.8)
Router Cache — client navigatsiya keshi (qaytgan sahifa darrov — server'ga so'rov yo'q)
Mutation'dan keyin revalidate (aks holda client eski ko'rsatadi — 2.6)Router Cache (4-qatlam, client) — client-side navigatsiya keshi. Router Cache — brauzer'da (client) tashrif buyurilgan sahifalar natijasini (RSC payload) saqlaydi — client navigatsiya tez bo'lishi uchun. Misol: foydalanuvchi
/products/about/products(qaytsa) — birinchi marta/productsserver'dan keladi, lekin qaytganda Router Cache'dan (brauzer xotirasida — server'ga bormaydi — darrov ko'rinadi). Xususiyatlari: (1) client'da (brauzer xotirasida — sessiya davomida — sahifa yangilansa yo'qoladi); (2)<Link>prefetch bilan to'ldiriladi (2.10 — havola ekranda ko'rinsa, Next.js uni oldindan yuklaydi — bosilganda darrov); (3) tez navigatsiya (qaytgan sahifa darrov — server'ga so'rov yo'q — SPA tajribasi); (4)router.refresh()yoki revalidate bilan tozalanadi. Tuzoq: mutation'dan keyin Router Cache eski ko'rsatishi mumkin (DB o'zgardi, lekin client keshda eski) — Server Action'darevalidatePathRouter Cache'ni ham yangilaydi (13.5: 2.8). Ikki nuqta: (1) Router Cache — client navigatsiya keshi (qaytgan sahifa darrov — server'ga so'rov yo'q — silliq, tez UX); (2) mutation'dan keyinrevalidate(aks holda client eski ko'rsatadi — eng keng "o'zgardi, lekin ko'rinmaydi" muammosi — 2.6). Bu — to'rt qatlamning yagona client tomonidagi (qolgan uchtasi server). Router Cache — Next.js navigatsiyasining tezligi (13.2<Link>)ning asosi. Bu qatlam SPA'dek silliq navigatsiya beradi, lekin mutation bilan ehtiyot bo'lishni talab qiladi.
2.6. Keshni boshqarish (revalidate, tags)
KESHHI BOSHQARISH — yangilash (revalidate) va tozalash (3 usul):
// 1. VAQT-ASOSLI (revalidate — N soniyadan keyin yangila):
fetch(url, { next: { revalidate: 3600 } }) // har 1 soat
export const revalidate = 3600; // butun sahifa
// 2. TEG-ASOSLI (tag + on-demand — eng moslashuvchan):
fetch(url, { next: { tags: ["products"] } }) // teg qo'y
// keyin (Server Action/Route'da):
import { revalidateTag } from "next/cache";
revalidateTag("products"); // "products" tegli HAMMA kesh yangila
// 3. YO'L-ASOSLI (revalidatePath — aniq yo'l):
import { revalidatePath } from "next/cache";
revalidatePath("/products"); // /products sahifa keshini yangila
QACHON QAYSI:
Davriy yangilansa yetadi revalidate: N (vaqt)
Aniq o'zgarish bo'lganda (admin tahrir) revalidateTag/Path (on-demand — darrov)
revalidate (vaqt) | revalidateTag (teg — moslashuvchan) | revalidatePath (aniq yo'l)
Mutation'dan keyin revalidate SHART (aks holda eski kesh — 2.5)Keshni boshqarish (revalidate, tags) — keshni yangilash va tozalashning usullari (eng muhim amaliy qism). Kesh (ayniqsa Data Cache va Full Route Cache) eskirishi mumkin (DB o'zgardi, lekin kesh eski) — uni yangilash uchun uch usul: (1) vaqt-asosli (
revalidate) —fetch(..., { next: { revalidate: 3600 } })yokiexport const revalidate = 3600(har N soniyada yangila — ISR — 13.4: 2.5 — davriy yangilansa yetadigan kontent); (2) teg-asosli (tags+revalidateTag) — eng moslashuvchan:fetch(..., { next: { tags: ["products"] } })(kesh'ga teg qo'y), keyinrevalidateTag("products")(next/cache'dan — "products" tegli barcha keshni yangila — masalan mahsulot o'zgarsa, barcha mahsulot-bog'liq sahifa); (3) yo'l-asosli (revalidatePath) —revalidatePath("/products")(aniq yo'l keshini yangila — 13.5: 2.8). Qachon qaysi: davriy yangilansa yetadirevalidate: N(vaqt); aniq o'zgarish bo'lganda (admin tahrir, foydalanuvchi amali)revalidateTag/revalidatePath(on-demand — darrov). Ikki nuqta: (1)revalidate(vaqt — avtomatik),revalidateTag(teg — bir o'zgarish ko'p sahifani yangilaydi — moslashuvchan),revalidatePath(aniq yo'l); (2) mutation'dan keyin revalidate shart (aks holda eski kesh — "o'zgardi, lekin ko'rinmaydi" — eng keng Next.js xatosi — 2.5). Teglar (RTK Query tags — 12.3 — kabi) eng kuchli (bir o'zgarish bog'liq sahifalarni yangilaydi). Bu — keshni boshqarishning amaliy yuragi (kesh tez, lekin to'g'ri yangilanishi shart).
2.7. Rasm optimizatsiyasi (next/image)
next/image — rasmni AVTOMATIK optimizatsiya (har saytning eng og'ir qismi):
import Image from "next/image";
<Image
src="/mahsulot.jpg"
width={800} // o'lcham (CLS'dan saqlaydi — joy zaxiralaydi)
height={600}
alt="Mahsulot" // alt — majburiy (accessibility + SEO)
priority // LCP rasmi (darrov yukla — yuqoridagi asosiy rasm)
/>
NEXT/IMAGE AVTOMATIK QILADIGAN ISH:
FORMAT — zamonaviy format (WebP/AVIF — JPG'dan 30% kichik)
O'LCHAM — qurilmaga mos (mobil kichik, desktop katta — responsive)
LAZY LOAD — ekranda ko'rinsa yuklaydi (pastdagi rasmlar keyin)
CLS YO'Q — width/height bilan joy zaxiralaydi (sakrash yo'q)
BLUR PLACEHOLDER — yuklanayotganda xira ko'rinish (silliq)
next/image — rasm avtomatik optimizatsiya (format, o'lcham, lazy, CLS) — <img>'dan ustun
width/height (CLS'dan) + alt (a11y) + priority (LCP rasmiga) MAJBURIY/muhimRasm optimizatsiyasi (next/image) — performance'ning eng katta g'alabasi (rasm — har saytning eng og'ir qismi).
next/image(Imagekomponenti) — rasmni avtomatik optimizatsiya qiladi (oddiy<img>'dan ustun). Ishlatish:<Image src="/mahsulot.jpg" width={800} height={600} alt="Mahsulot" priority />. Avtomatik qiladigan ish: (1) format — rasmni zamonaviy formatga (WebP/AVIF — JPG'dan ~30% kichik) o'giradi (brauzer qo'llasa); (2) o'lcham — qurilmaga mos o'lchamda beradi (mobil uchun kichik, desktop uchun katta — responsive — keraksiz katta rasm yuklanmaydi); (3) lazy load — rasm ekranda ko'rinsa yuklaydi (pastdagi rasmlar foydalanuvchi pastga tushganda — boshlang'ich yuk kam); (4) CLS yo'q —width/heightbilan joy oldindan zaxiralaydi (rasm yuklanayotganda sahifa "sakramaydi" — Cumulative Layout Shift — 2.9); (5) blur placeholder — yuklanayotganda xira ko'rinish (silliq tajriba). Muhim atributlar:width/height(CLS'dan — majburiy),alt(accessibility + SEO — majburiy),priority(LCP rasmiga — yuqoridagi asosiy rasm darrov yuklansin — 2.9). Ikki nuqta: (1)next/image— rasm avtomatik optimizatsiya (format, o'lcham, lazy, CLS) — oddiy<img>'dan ancha ustun (qo'lda qilish qiyin ishlarni avtomatik); (2)width/height(CLS'dan),alt(a11y),priority(LCP asosiy rasmiga) — muhim. Bu — Next.js'ning eng oson va eng katta ta'sirli performance optimizatsiyasi (rasm og'ir — uni optimizatsiya qilish sahifani sezilarli tezlashtiradi). Har Next.js loyihada<img>o'rniga<Image>ishlatish — birinchi optimizatsiya qadami.
2.8. Shrift va skript (next/font, next/script)
next/font — shriftni OPTIMIZATSIYA (layout shift'siz, tez, maxfiy):
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] }); // build paytida yuklanadi (self-hosted)
<body className={inter.className}>...</body>
Shrift O'Z serveringizda (Google'ga so'rov yo'q — tez, maxfiylik)
Layout shift yo'q (shrift o'lchami oldindan hisoblanadi — CLS yo'q)
Faqat kerakli belgilar (subset — kichik fayl)
next/script — skriptni TO'G'RI yuklash (3-tomon — analytics, chat):
import Script from "next/script";
<Script src="https://analytics.com/script.js" strategy="afterInteractive" />
STRATEGIYALAR:
- beforeInteractive — sahifadan oldin (kritik — kam)
- afterInteractive — sahifa interaktiv bo'lgach (analytics — default)
- lazyOnload — bo'sh vaqtda (chat widget — eng past ustuvorlik)
next/font — shrift self-hosted (tez, CLS yo'q, maxfiy); next/script — strategiya bilan
Shrift/skript — performance'ning nozik, lekin sezilarli qismlariShrift va skript (next/font, next/script) — performance'ning nozik, lekin sezilarli qismlari.
next/font— shriftni optimizatsiya qiladi:import { Inter } from "next/font/google"; const inter = Inter({ subsets: ["latin"] })— Google Font'ni build paytida yuklab, o'z serveringizda joylashtiradi (self-hosted). Afzalliklar: (1) shrift o'z serveringizda (Google'ga so'rov yo'q — tezroq, maxfiylik — Google foydalanuvchini kuzatmaydi); (2) layout shift yo'q (shrift o'lchami oldindan hisoblanadi — matn shrift yuklanganda "sakramaydi" — CLS yo'q — 2.9); (3) faqat kerakli belgilar (subsets— masalan faqat lotin — kichik fayl).next/script— 3-tomon skriptlarini (analytics, chat widget, reklama) to'g'ri yuklaydi:<Script src="..." strategy="afterInteractive" />. Strategiyalar:beforeInteractive(sahifadan oldin — kritik skript — kam ishlatiladi),afterInteractive(sahifa interaktiv bo'lgach — analytics — default — sahifani bloklamaydi),lazyOnload(bo'sh vaqtda — chat widget — eng past ustuvorlik — sahifa yuklanganidan keyin). Ikki nuqta: (1)next/font— shrift self-hosted (tez, CLS yo'q, maxfiy);next/script— strategiya bilan (skript sahifani bloklamasin); (2) shrift/skript — performance'ning nozik, lekin sezilarli qismlari (optimizatsiya qilinmasa — sekinlashtiradi). Bu ikki —next/image2.7-bob bilan birga Next.js'ning o'rnatilgan performance vositalari (rasm, shrift, skript — sahifaning eng og'ir uch qismi). Ularni to'g'ri ishlatish — sezilarli tezlik (ayniqsa Core Web Vitals — 2.9).
2.9. Core Web Vitals (LCP, CLS, INP)
CORE WEB VITALS — Google'ning tezlik o'lchovlari (SEO + UX'ga ta'sir):
┌──────┬─────────────────────────┬─────────────┬──────────────────────┐
│ Metr │ Nima o'lchaydi │ Yaxshi │ Qanday yaxshilash │
├──────┼─────────────────────────┼─────────────┼──────────────────────┤
│ LCP │ eng katta element yuklash│ < 2.5s │ next/image priority, │
│ │ (asosiy rasm/matn) │ │ SSR/SSG, kesh │
│ CLS │ layout sakrash │ < 0.1 │ width/height, font, │
│ │ (kontent siljishi) │ │ joy zaxira │
│ INP │ interaktivlikka javob │ < 200ms │ kam JS, Server Comp, │
│ │ (bosishga reaksiya) │ │ code splitting │
└──────┴─────────────────────────┴─────────────┴──────────────────────┘
NEXT.JS YORDAMI (bu metrlarni avtomatik yaxshilaydi):
SSR/SSG (LCP tez — server HTML); Server Components (INP — kam JS)
next/image (LCP + CLS); next/font (CLS)
LCP (yuklash), CLS (sakrash), INP (javob) — Google'ning 3 asosiy tezlik metri
Next.js bularni avtomatik yaxshilaydi (SSR/SSG, image, font, kam JS)Core Web Vitals (LCP, CLS, INP) — Google'ning tezlik o'lchovlari (SEO va UX'ga to'g'ridan ta'sir). Uch asosiy metr: (1) LCP (Largest Contentful Paint) — eng katta element (asosiy rasm yoki matn bloki) yuklash vaqti (yaxshi: < 2.5 soniya) — foydalanuvchi asosiy kontentni qachon ko'radi; yaxshilash:
next/image priority2.7-bob, SSR/SSG (13.4 — server tayyor HTML), kesh; (2) CLS (Cumulative Layout Shift) — layout sakrash (kontent yuklanganda siljishi — masalan rasm yuklanganda matn pastga sakrashi — yomon UX) (yaxshi: < 0.1); yaxshilash:width/height(rasm — 2.7),next/font(shrift — 2.8), joy zaxiralash; (3) INP (Interaction to Next Paint) — interaktivlikka javob (foydalanuvchi bosganda qancha tez reaksiya — yaxshi: < 200ms); yaxshilash: kam JavaScript (Server Components — 13.3 — kam JS brauzerga), code splitting 2.10-bob. Next.js yordami — bu metrlarni avtomatik yaxshilaydi: SSR/SSG (LCP tez — server HTML), Server Components (INP — kam JS),next/image(LCP + CLS),next/font(CLS). Ikki nuqta: (1) LCP (yuklash), CLS (sakrash), INP (javob) — Google'ning 3 asosiy tezlik metri (Google bularni qidiruv reytingida ishlatadi — tez sayt yuqoriroq); (2) Next.js bularni avtomatik yaxshilaydi (SSR/SSG, image, font, kam JS — to'g'ri ishlatsa). Bu metrlar — performance optimizatsiyasining maqsadi (nimani o'lchaymiz). PageSpeed Insights yoki Chrome DevTools (Lighthouse) bilan o'lchanadi. Tez sayt = yaxshi SEO + ko'proq foydalanuvchi (sekin sayt — odamlar ketadi). Core Web Vitals — performance'ning "imtihon" balli.
2.10. Lazy loading, prefetch va best practices
next/dynamic — komponentni FAQAT KERAK bo'lganda yuklash (lazy loading — 11.8):
import dynamic from "next/dynamic";
const HeavyChart = dynamic(() => import("./HeavyChart"), {
loading: () => <Skeleton />, // yuklanayotganda
ssr: false, // faqat client'da (og'ir, brauzer-only)
});
HeavyChart faqat kerak bo'lganda yuklanadi (boshlang'ich bundle kichik)
PREFETCH — <Link> avtomatik oldindan yuklash (Router Cache'ni to'ldiradi — 2.5):
<Link href="/products">...</Link> // ekranda ko'rinsa — /products oldindan yuklanadi
bosilganda DARROV (allaqachon yuklangan)
PERFORMANCE BEST PRACTICES:
next/image (rasm — 2.7); next/font (shrift — 2.8)
Server Components default (kam JS — 13.3); "use client" minimal (13.3: 2.6)
next/dynamic (og'ir komponent — lazy)
Statik/ISR default (tez — 13.4); kesh to'g'ri (revalidate — 2.6)
Parallel fetch (waterfall'dan — 13.5: 2.2)
Bundle tahlil (@next/bundle-analyzer — katta paketni top)
next/dynamic — og'ir komponent lazy (boshlang'ich bundle kichik); <Link> prefetch (tez nav)
Performance: image+font+Server Components+statik+kesh+lazy (birga — tez ilova)Lazy loading, prefetch va best practices — performance optimizatsiyasining yakuni.
next/dynamic— komponentni faqat kerak bo'lganda yuklash (lazy loading — 11.8React.lazyning Next.js versiyasi):const HeavyChart = dynamic(() => import("./HeavyChart"), { loading: () => <Skeleton />, ssr: false })—HeavyChart(og'ir komponent — masalan grafik kutubxonasi) faqat kerak bo'lganda yuklanadi (boshlang'ich bundle kichik — sahifa tezroq yuklanadi),ssr: false(faqat client'da — brauzer-only komponent uchun). Prefetch —<Link>avtomatik oldindan yuklash (Router Cache'ni to'ldiradi — 2.5):<Link href="/products">— havola ekranda ko'rinsa, Next.js/productsni oldindan yuklaydi (bosilganda darrov — allaqachon yuklangan — silliq navigatsiya). Performance best practices (butun bobni umumlashtiradi): (1)next/image(rasm — 2.7),next/font(shrift — 2.8); (2) Server Components default (kam JS — 13.3),"use client"minimal (13.3: 2.6); (3)next/dynamic(og'ir komponent — lazy); (4) statik/ISR default (tez — 13.4), kesh to'g'ri (revalidate — 2.6); (5) parallel fetch (waterfall'dan — 13.5: 2.2); (6) bundle tahlil (@next/bundle-analyzer— katta paketni topib optimizatsiya). Ikki nuqta: (1)next/dynamic— og'ir komponentni lazy (boshlang'ich bundle kichik),<Link>prefetch (tez navigatsiya); (2) performance — image + font + Server Components + statik + kesh + lazy (birga ishlab — tez ilova). Bu — Next.js performance optimizatsiyasining to'liq to'plami. Har biri kichik, lekin birga katta ta'sir (tez sayt — yaxshi UX, SEO, konversiya). Performance — bir marta qilinadigan emas, doimiy e'tibor (o'lcha — Core Web Vitals, optimizatsiya qil, qayta o'lcha).
2.11. Next.js 15 kesh o'zgarishlari va opt-out
NEXT.JS 15 — KESH DEFAULT'LARI O'ZGARDI (14 15 — muhim farq):
┌──────────────────────────┬──────────────┬───────────────────┐
│ Nima │ Next.js 14 │ Next.js 15 │
├──────────────────────────┼──────────────┼───────────────────┤
│ fetch() default │ KESHLANADI │ KESHLANMAYDI │
│ GET Route Handler │ KESHLANADI │ KESHLANMAYDI │
│ Router Cache (sahifa) │ 30s kesh │ 0s (default) │
└──────────────────────────┴──────────────┴───────────────────┘
// 15'da keshlash uchun ENDI OSHKOR aytish kerak:
fetch(url, { cache: "force-cache" }) // yoki
fetch(url, { next: { revalidate: 3600 } }) // aniq revalidate
// "use cache" (yangi, eksperimental direktiva — funksiya/fayl/komponentni keshlaydi):
async function getData() {
"use cache"; // shu funksiya natijasi keshlanadi
return db.query("SELECT ...");
}
KESHNI OCHIQ O'CHIRISH (opt-out — sahifa dinamik bo'lsin):
export const dynamic = "force-dynamic"; // butun sahifa dinamik (kesh yo'q)
cookies() / headers() // chaqirilsa — sahifa avtomatik dinamik
Next.js 15: default UNCACHED (fetch/GET Route — oshkor force-cache/revalidate kerak)
"use cache" — kelajakdagi model (fetch'siz ham funksiyani keshlash)Next.js 15 kesh o'zgarishlari va opt-out — 14'dan 15'ga o'tishdagi eng muhim xatti-harakat farqi. Next.js 14'da
fetchdefault keshlanardi (force-cache— kutilmagan eski ma'lumot muammosi), 15'da esa default keshlanmaydi (no-store— har doim yangi, lekin kutilmagan takror so'rov). Xuddi shunday: GET Route Handler 13.6-bob 14'da keshlanardi, 15'da yo'q; Router Cache sahifa segmentlari 14'da 30 soniya keshlanardi, 15'da 0 soniya (default — har navigatsiyada yangi). Xulosa: Next.js 15'da keshlashni oshkor aytish kerak —fetch(url, { cache: "force-cache" })yokinext: { revalidate: N }. Yangi model —"use cache"direktivasi (eksperimental): funksiya, fayl yoki komponent boshiga"use cache"yozilsa, uning natijasi keshlanadi (fetch'siz ham — masalan DB so'rovi natijasi) — bu Next.js kelajakdagi kesh modeli (barcha kesh bir direktiva ostida). Keshni ochiq o'chirish (opt-out — sahifa dinamik bo'lishi kerak bo'lganda):export const dynamic = "force-dynamic"(butun sahifa har so'rovda render — kesh yo'q — 13.4: 2.6), yoki dinamik funksiyalar —cookies()/headers()chaqirilsa, sahifa avtomatik dinamik bo'ladi (chunki javob har foydalanuvchiga xos — keshlanmaydi). Ikki nuqta: (1) Next.js 15 default uncached (fetch/GET Route — oshkorforce-cache/revalidatekerak — 14'dan katta farq, migratsiyada diqqat); (2)"use cache"— kelajakdagi yagona kesh direktivasi (fetch'siz ham keshlash). Bu o'zgarish — 14 loyihasini 15'ga ko'chirganda "nega endi keshlanmayapti?" muammosining sababi (default o'zgargan). Qaysi versiyada ekaningizni bilib, kesh strategiyasini oshkor yozish kerak.
2.12. Router Cache sozlash, unstable_cache va React cache
ROUTER CACHE'ni SOZLASH (staleTimes — client kesh muddati):
// next.config.js
experimental: {
staleTimes: { dynamic: 30, static: 180 }, // dinamik 30s, statik 180s kesh
}
DB SO'ROVINI KESHLASH (fetch EMAS — 2 usul):
// 1. React cache() — BIR render davomida dedup (Request Memoization'ning DB versiyasi):
import { cache } from "react";
export const getUser = cache(async (id) => db.user.findUnique({ where: { id } }));
// bir render'da getUser(1) ko'p marta chaqirilsa — DB'ga 1 marta (13.5: Misol 9)
// 2. unstable_cache() — DOIMIY Data Cache (so'rovlar aro — revalidate/tag bilan):
import { unstable_cache } from "next/cache";
export const getProducts = unstable_cache(
async () => db.product.findMany(),
["products-list"], // kesh kaliti
{ revalidate: 3600, tags: ["products"] }, // 1 soat + teg (revalidateTag ishlaydi)
);
React cache() — bir render dedup (DB uchun Request Memoization); unstable_cache — doimiy Data Cache (DB uchun)
staleTimes — Router Cache muddatini sozlash (client navigatsiya keshi)Router Cache sozlash, unstable_cache va React cache — kesh boshqaruvining ilg'or vositalari (
fetch'dan tashqari). Uch qism: (1) Router Cache sozlash (staleTimes) — client-side Router Cache 2.5-bob muddatininext.config.js'da sozlash:experimental: { staleTimes: { dynamic: 30, static: 180 } }(dinamik sahifalar 30 soniya, statik sahifalar 180 soniya client keshda — Next.js 15'da default 0 bo'lgani uchun, agar navigatsiya keshini xohlansa shu bilan yoqiladi); (2) Reactcache()—fetchemas, DB yoki har qanday async funksiyani bir render davomida dedup qiladi (Request Memoization'ning — 2.2 — DB versiyasi):export const getUser = cache(async (id) => db.user.findUnique(...))— bir render'dagetUser(1)ko'p komponentdan chaqirilsa, DB'ga faqat bir marta (13.5: Misol 9); (3)unstable_cache()— DB so'rovini doimiy Data Cache'ga 2.3-bob qo'yadi (so'rovlar va deploylar aro):unstable_cache(fn, keys, { revalidate, tags })— birinchi argument funksiya, ikkinchi kesh kaliti, uchinchi opsiyalar (revalidate— vaqt,tags—revalidateTagishlashi uchun). Ikki nuqta: (1) Reactcache()— bir render dedup (DB uchun Request Memoization — qisqa),unstable_cache— doimiy Data Cache (DB uchun — uzun, revalidate/tag bilan boshqariladi); (2)staleTimes— Router Cache muddatini sozlash (client navigatsiya keshi). Bularning muhimligi:fetchkeshi 2.3-bob faqatfetchuchun — Prisma/Drizzle kabi ORM'lar DB'ga to'g'ridan boradi (fetchemas), shuning uchun ularni keshlash uchuncache()(bir render) yokiunstable_cache()(doimiy) ishlatiladi. Demak DB'li ilovada 13.9-bob kesh —unstable_cacheorqali (fetchkeshi ishlamaydi). Bu — kesh qatlamlarini (2.1)fetch'siz ma'lumot manbalariga (DB, ORM) kengaytirish.
2.13. Partial Prerendering, third-parties va edge/CDN
PARTIAL PRERENDERING (PPR) — bitta sahifada STATIK + DINAMIK (eng yangi model):
sahifaning statik qismi build'da (darrov — Full Route Cache),
dinamik qismi Suspense ichida (stream — har so'rov)
// app/page.tsx
export const experimental_ppr = true;
<StaticHeader /> {/* statik — darrov (kesh) */}
<Suspense fallback={<Skeleton />}>
<DynamicCart /> {/* dinamik — stream (har foydalanuvchi) */}
</Suspense>
@next/third-parties — 3-tomon skriptni OPTIMAL (analytics, YouTube, xarita):
import { GoogleAnalytics } from "@next/third-parties/google";
<GoogleAnalytics gaId="G-XXXX" /> // optimizatsiyalangan (next/script ustida)
EDGE / CDN KESH (Vercel va boshqa platformalar):
statik sahifa/rasm — CDN'da global (foydalanuvchiga eng yaqin server — tez)
ISR/revalidate — edge'da tarqatiladi; Speed Insights — real foydalanuvchi Web Vitals
PPR — bir sahifada statik (tez) + dinamik (shaxsiy) birga (Full Route + streaming)
@next/third-parties — 3-tomon skript optimal; CDN/edge — statik global tezPartial Prerendering, third-parties va edge/CDN — Next.js performance'ining eng yangi va platforma darajasidagi qatlamlari. Uch mavzu: (1) Partial Prerendering (PPR) — Next.js'ning eng yangi rendering modeli (eksperimental): bitta sahifada statik va dinamik qismlarni birlashtiradi. Muammo — ilgari sahifa yo butun statik (tez, lekin shaxsiy ma'lumot yo'q), yo butun dinamik (shaxsiy, lekin sekin) edi. PPR bilan: sahifaning statik qismi (masalan sarlavha, mahsulot ma'lumoti) build paytida generatsiya (Full Route Cache — darrov ko'rinadi), dinamik qismi (masalan savat, foydalanuvchi nomi)
<Suspense>ichida stream bo'ladi (har foydalanuvchiga xos).export const experimental_ppr = truebilan yoqiladi. Natija — statik tezlik (darrov shell) + dinamik moslik (shaxsiy qism keladi) — ikkisi bir sahifada; (2)@next/third-parties— mashhur 3-tomon skriptlarni (Google Analytics, Google Maps, YouTube embed) optimal yuklaydi:import { GoogleAnalytics } from "@next/third-parties/google"; <GoogleAnalytics gaId="G-XXXX" />— bunext/script2.8-bob ustiga qurilgan, tayyor va optimizatsiyalangan komponentlar (strategyqo'lda sozlanmaydi — performance'ga zarar bermaydigan tarzda); (3) edge/CDN kesh — statik sahifa va rasmlar CDN'da (Vercel yoki boshqa platforma) global tarqatiladi — foydalanuvchiga eng yaqin serverdan beriladi (tarmoq kechikishi kam — tez). ISR/revalidate edge'da ishlaydi; Speed Insights (Vercel) — real foydalanuvchilardan Core Web Vitals 2.9-bobni to'playdi (Lighthouse — laboratoriya sinovi; Speed Insights — dala ma'lumoti). Ikki nuqta: (1) PPR — bir sahifada statik (tez shell) + dinamik (shaxsiy, stream) birga (Full Route Cache + streaming — 13.4: 2.8 — birlashuvi); (2)@next/third-parties— 3-tomon skript optimal; CDN/edge — statik global tez (deploy — 13.11). Bu qatlamlar — Next.js'ning kesh va performance modelini platforma (deploy, CDN) darajasiga kengaytiradi. PPR — kelajakdagi default rendering (statik va dinamik chegarasini yo'qotadi).
3. Sintaksis — tez ma'lumotnoma
4 KESH 2.1-bob: Memoization(1 render) | Data(fetch doimiy) | Full Route(HTML) | Router(client)
DATA CACHE 2.3-bob: fetch(url, { cache: "force-cache" | "no-store", next: { revalidate, tags } })
REVALIDATE 2.6-bob: export const revalidate=N | revalidateTag("x") | revalidatePath("/y")
IMAGE 2.7-bob: <Image src width height alt priority />
FONT 2.8-bob: const inter = Inter({ subsets: ["latin"] }) className={inter.className}
SCRIPT 2.8-bob: <Script src strategy="afterInteractive" />
DYNAMIC 2.10-bob: const C = dynamic(() => import("./C"), { loading, ssr: false })
PREFETCH 2.10-bob: <Link href="/x"> (avtomatik prefetch)
VITALS 2.9-bob: LCP < 2.5s | CLS < 0.1 | INP < 200ms
NEXT 15 2.11-bob: fetch default NO-STORE | "use cache" | export const dynamic="force-dynamic"
DB KESH 2.12-bob: cache(fn) [render dedup] | unstable_cache(fn, keys, { revalidate, tags })
ROUTER 2.12-bob: experimental: { staleTimes: { dynamic, static } }
PPR 2.13-bob: export const experimental_ppr = true (statik + dinamik bir sahifada)
3-TOMON 2.13-bob: import { GoogleAnalytics } from "@next/third-parties/google"4. Batafsil kod namunalari
Har misol: Maqsad + izohli kod + "Bu kod nima qiladi".
Misol 1 — Data Cache strategiyalari (2.3, 2.6)
Maqsad: Bir sahifada turli ma'lumotlarni turli kesh strategiyasi bilan olish — qaysi ma'lumot qancha keshlanishi kerakligini ko'rsatish. Bu kesh boshqaruvining amaliy asosi.
// app/page.tsx — Server Component (har ma'lumot o'z kesh strategiyasi bilan)
export default async function HomePage() {
// 1. STATIK ma'lumot (kam o'zgaradi — doimiy kesh):
const categories = await fetch("https://api.example.com/categories", {
cache: "force-cache", // doimiy Data Cache (kategoriyalar kam o'zgaradi)
}).then((r) => r.json());
// 2. DAVRIY yangilanadigan (mahsulotlar — har 10 daqiqa):
const products = await fetch("https://api.example.com/products", {
next: { revalidate: 600, tags: ["products"] }, // 10 daqiqa + teg (on-demand uchun)
}).then((r) => r.json());
// 3. DOIM YANGI (jonli zaxira — har so'rov):
const stock = await fetch("https://api.example.com/stock", {
cache: "no-store", // keshlama (har so'rov yangi)
}).then((r) => r.json());
return <div>{/* categories, products, stock */}</div>;
}Bu kod nima qiladi: Bu — kesh strategiyasini har ma'lumotga moslash (2.3, 2.6 — amaliy asos). Bir sahifada uch xil ma'lumot, har biri turli kesh: (1) kategoriyalar — cache: "force-cache" (doimiy Data Cache — kategoriyalar juda kam o'zgaradi, shuning uchun bir marta olib, doimiy keshlash — har so'rovda DB'ga bormaydi — eng tez); (2) mahsulotlar — next: { revalidate: 600, tags: ["products"] } (10 daqiqa kesh — mahsulotlar vaqti-vaqti o'zgaradi, 10 daqiqada bir yangilansa yetadi; tags: ["products"] — on-demand yangilash uchun teg — admin mahsulot qo'shsa revalidateTag("products") bilan darrov yangilash mumkin — 2.6); (3) zaxira (stock) — cache: "no-store" (keshlama — har so'rovda yangi — zaxira jonli o'zgaradi, eski ko'rsatish xato bo'lardi — "bor" degan mahsulot aslida tugagan bo'lishi mumkin). Demak har ma'lumot o'z o'zgarish tezligiga qarab keshlanadi: kam o'zgaradigan doimiy kesh (tez), o'rta davriy (revalidate), tez o'zgaradigan kesh yo'q (yangi). Bu — kesh boshqaruvining yuragi: "bu ma'lumot qancha tez eskiradi?" deb o'ylab, mos strategiya tanlash. Diqqat: bu uch fetch ketma-ket (waterfall) — agar bog'liq bo'lmasa, Promise.all bilan parallel qilish kerak (13.5: 2.2 — bu yerda soddalik uchun ketma-ket ko'rsatildi). To'g'ri kesh — tez sayt + to'g'ri ma'lumot balansi.
Misol 2 — On-demand revalidation (teg bilan — 2.6)
Maqsad: Admin mahsulot o'zgartirganda teg orqali barcha bog'liq sahifani darrov yangilash — revalidateTag. Bu kesh tezligi + darrov yangilanishning eng kuchli birikmasi.
// app/admin/actions.ts — Server Action (admin mahsulot o'zgartiradi)
"use server";
import { revalidateTag } from "next/cache";
export async function updateProduct(id: string, formData: FormData) {
await db.product.update({
where: { id },
data: { price: Number(formData.get("price")) },
});
// "products" tegli BARCHA keshni yangila (bir amal, ko'p sahifa):
revalidateTag("products");
// bosh sahifa, mahsulot ro'yxati, bu mahsulot — HAMMASI yangilanadi (teg orqali)
}
// Eslatma: bu sahifalar "products" tegi bilan fetch qilgan (Misol 1):
// fetch(..., { next: { tags: ["products"] } })
// revalidateTag("products") ularning HAMMASINI yangilaydiBu kod nima qiladi: Bu — teg-asosli on-demand revalidation (2.6 — kesh boshqaruvining eng kuchli usuli). Muammo: admin mahsulot narxini o'zgartirsa, bu mahsulot ko'p sahifada ko'rinadi (bosh sahifa, mahsulot ro'yxati, mahsulot sahifasi, savat) — hammasi keshda (eski narx). Har birini revalidatePath bilan alohida yangilash zerikarli (qaysi sahifalarda ekanini eslab qolish kerak). Yechim — teglar: barcha mahsulot-bog'liq fetch'lar tags: ["products"] bilan keshlangan (Misol 1), keyin admin o'zgartirsa revalidateTag("products") — bu bitta amal "products" tegli barcha keshni yangilaydi (bosh sahifa, ro'yxat, mahsulot — hammasi — teg orqali bog'langan). Ya'ni teg — keshni guruhlash mexanizmi (bir o'zgarish bir guruh keshni yangilaydi). Bu RTK Query'ning tag invalidation'iga (12.3: 2.6) juda o'xshaydi (bir mutation bog'liq query'larni yangilaydi). Demak: revalidatePath — aniq bir yo'l (qaysi sahifani bilsangiz); revalidateTag — bog'liq sahifalar guruhi (bir o'zgarish hammasini yangilaydi — moslashuvchanroq). Admin paneli, CMS uchun teglar ideal (bir tahrir — barcha bog'liq joy darrov yangilanadi, lekin qolgan kesh tegmaydi — tezlik saqlanadi). Bu — kesh tezligi (statik) + darrov yangilanish (on-demand) ning eng yaxshi birikmasi (e-commerce, CMS uchun).
Misol 3 — next/image to'liq (2.7, 2.9)
Maqsad: Rasmlarni to'liq optimizatsiya qilish — LCP rasmi, lazy rasmlar, responsive, blur. Bu sahifa tezligining (LCP, CLS) eng katta yaxshilanishi.
import Image from "next/image";
export default function ProductPage({ product }: { product: Product }) {
return (
<div>
{/* ASOSIY rasm (LCP — yuqopida — darrov yukla): */}
<Image
src={product.image}
width={1200}
height={800}
alt={product.name}
priority // LCP rasmi (lazy EMAS — darrov — 2.9)
placeholder="blur" // yuklanayotganda xira
blurDataURL={product.blurHash}
/>
{/* Galereya rasmlapi (pastda — lazy — default): */}
<div className="gallery">
{product.gallery.map((img, i) => (
<Image
key={i}
src={img}
width={400}
height={300}
alt={`${product.name} ${i + 1}`}
// priority YO'Q lazy (ekranda ko'rinca yuklanadi — boshlang'ich yuk kam)
/>
))}
</div>
</div>
);
}Bu kod nima qiladi: Bu — rasmlarni to'liq optimizatsiya (2.7, 2.9 — LCP va CLS yaxshilash). Ikki xil rasm, ikki xil yondashuv: (1) asosiy rasm (mahsulotning katta rasmi — sahifaning eng katta, eng muhim elementi — LCP — 2.9): priority atributi bilan — bu Next.js'ga "bu rasm muhim, darrov yukla (lazy qilma)" deydi (LCP rasmi tez yuklansa — sahifa tez "to'lgan"dek ko'rinadi — Core Web Vitals yaxshilanadi). placeholder="blur" + blurDataURL — yuklanayotganda xira (kichik) versiya ko'rinadi (silliq — bo'sh joy emas); (2) galereya rasmlari (pastda — kichik): priority yo'q default lazy (ekranda ko'rinsa yuklanadi — foydalanuvchi pastga tushganda — boshlang'ich yuk kam — sahifa tez yuklanadi). Har rasmda width/height (joy oldindan zaxiralanadi — rasm yuklanganda sahifa sakramaydi — CLS yo'q — 2.9), alt (accessibility — ekran o'qiguvchi uchun, va SEO). next/image orqali: har rasm WebP/AVIF (kichik format), qurilmaga mos o'lcham (responsive), lazy (pastdagilar). Demak: asosiy rasm priority (LCP tez), qolgani lazy (boshlang'ich yuk kam), hammasi width/height (CLS yo'q) va alt (a11y). Bu — rasm og'ir bo'lgan sahifani (e-commerce, galereya, blog) sezilarli tezlashtiradi. Keng xato: asosiy (LCP) rasmga priority qo'ymaclik (lazy bo'lib qoladi — LCP sekin); yoki barcha rasmga priority (hammasini darrov — boshlang'ich yuk katta). To'g'ri: faqat LCP (yuqoridagi asosiy) rasmga priority, qolgani lazy.
Misol 4 — next/font (shrift optimizatsiyasi — 2.8)
Maqsad: Shriftni self-hosted, CLS'siz yuklash — next/font bilan. Bu shrift sababli layout sakrashni (CLS) yo'qotadi va maxfiylikni oshipadi.
// app/layout.tsx — Root layout (shrift butun ilova uchun)
import { Inter, Roboto_Mono } from "next/font/google";
// Asosiy shrift (matn uchun):
const inter = Inter({
subsets: ["latin"], // faqat lotin (kichik fayl)
display: "swap", // shrift yuklangyncha tizim shrifti (FOIT'dan saqlaydi)
variable: "--font-inter", // CSS o'zgaruvchi (Tailwind bilan)
});
// Kod uchun monospace shrift:
const robotoMono = Roboto_Mono({ subsets: ["latin"], variable: "--font-mono" });
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="uz" className={`${inter.variable} ${robotoMono.variable}`}>
<body className={inter.className}>{children}</body> {/* shrift qo'llandi */}
</html>
);
}Bu kod nima qiladi: Bu — shrift optimizatsiyasi (2.8 — CLS va maxfiylik). next/font/google'dan shrift import qilinadi (Inter — matn, Roboto_Mono — kod). Sozlamalar: subsets: ["latin"] (faqat lotin belgilari — kichik fayl, kirill/xitoy keraksiz), display: "swap" (shrift yuklanguncha tizim shrifti ko'rsatiladi, keyin almashtiriladi — matn darrov ko'rinadi, "ko'rinmas matn" — FOIT — muammosini oldini oladi), variable (CSS o'zgaruvchi — Tailwind yoki CSS bilan ishlatish uchun). Eng muhim: next/font shriftni build paytida yuklab, o'z serveringizda joylashtiradi (self-hosted) — natijada: (1) Google'ga so'rov yo'q (tezroq — tashqi so'rov kechikishi yo'q; maxfiylik — Google foydalanuvchi IP'sini olmaydi); (2) shrift o'lchami oldindan ma'lum (CSS'da joy zaxiralanadi — shrift yuklanganda matn "sakramaydi" — CLS yo'q — 2.9 — eng katta foyda). inter.className — shriftni <body>ga qo'llaydi (butun ilova shu shrift). Demak: shrift tez (self-hosted), CLS yo'q (display: swap + o'lcham), maxfiy (Google'ga so'rov yo'q), kichik (subset). Oddiy <link href="fonts.googleapis.com"> (eski usul) bularning hech birini bermasdi (Google'ga so'rov, CLS, kechikish). next/font — shrift bilan ishlashning zamonaviy, optimal usuli (har Next.js loyihada). Shrift — sahifaning nozik, lekin har joyda ko'rinadigan qismi (matn) — uni optimizatsiya qilish CLS va tezlikka sezilarli ta'sir.
Misol 5 — Lazy loading (next/dynamic — 2.10)
Maqsad: Og'ir komponentni (grafik) faqat kerak bo'lganda yuklash — next/dynamic bilan. Bu boshlang'ich bundle'ni kichik tutib, sahifani tezlashtiradi.
// app/dashboard/page.tsx
"use client";
import { useState } from "react";
import dynamic from "next/dynamic";
// Og'ir grafik kutubxonasi — FAQAT kerak bo'lganda yuklanadi:
const AnalyticsChart = dynamic(() => import("./AnalyticsChart"), {
loading: () => <div className="skeleton">Grafik yuklanmoqda...</div>, // yuklanayotganda
ssr: false, // faqat client'da (grafik kutubxonasi brauzep-only)
});
export default function Dashboard() {
const [showChart, setShowChart] = useState(false);
return (
<div>
<h1>Dashboard</h1>
<button onClick={() => setShowChart(true)}>Grafikni ko'rsat</button>
{/* Grafik faqat tugma bosilgach yuklanadi (boshlang'ich bundle'da YO'Q): */}
{showChart && <AnalyticsChart />}
</div>
);
}Bu kod nima qiladi: Bu — lazy loading (og'ir komponentni faqat kerak bo'lganda yuklash — 2.10). AnalyticsChart — og'ir komponent (grafik kutubxonasi — masalan Recharts, Chart.js — katta JavaScript). Agar uni oddiy import qilsak (import AnalyticsChart from "./AnalyticsChart"), uning butun JavaScript'i boshlang'ich bundle'ga qo'shiladi (sahifa birinchi yuklanganda — garchi grafik hali ko'rsatilmagan bo'lsa ham — keraksiz og'irlik). next/dynamic bilan: const AnalyticsChart = dynamic(() => import("./AnalyticsChart"), {...}) — grafik kodi alohida bo'lakka ajratiladi (code splitting — 11.8), va faqat kerak bo'lganda (tugma bosilib showChart true bo'lganda) yuklanadi. loading — yuklanayotganda ko'rsatiladigan UI (skeleton), ssr: false (grafik faqat client'da — server'da render qilmaslik — chunki grafik kutubxonasi brauzer DOM'iga muhtoj, server'da xato bermasin). Natija: sahifa birinchi yuklanganda grafik JavaScript'i yuklanmaydi (boshlang'ich bundle kichik — sahifa tez), faqat foydalanuvchi "Grafikni ko'rsat" bosganda grafik kodi yuklanadi (kerak bo'lganda). Bu — React.lazy 11.8-bobning Next.js versiyasi, lekin ssr opsiyasi va loading bilan qulayroq. Qachon kerak: og'ir, har doim kerak bo'lmaydigan komponentlar (grafik, xarita, video pleer, og'ir editor, modal ichidagi murakkab forma). Lazy loading — boshlang'ich bundle'ni kichik tutishning (INP, LCP yaxshilash — 2.9) asosiy usuli. Hamma narsani darrov yuklash emas — keraklisini kerak bo'lganda.
Misol 6 — Parallel fetch + Suspense (2.3, streaming)
Maqsad: Bir sahifada parallel fetch + streaming bilan eng tez yuklanish — tez qism darrov, sekin qism keyinroq. Bu performance'ning bir necha texnikasini birlashtiradi.
// app/profile/page.tsx — Server Component
import { Suspense } from "react";
// Tez ma'lumot (asosiy — darrov):
async function ProfileHeader({ userId }: { userId: string }) {
const user = await fetch(`/api/users/${userId}`, { next: { revalidate: 60 } }).then((r) => r.json());
return <h1>{user.name}</h1>;
}
// Sekin ma'lumot (tahlil — alohida Suspense):
async function ProfileStats({ userId }: { userId: string }) {
const stats = await fetch(`/api/users/${userId}/stats`, { cache: "no-store" }).then((r) => r.json());
return <div>{stats.posts} post · {stats.followers} obunachi</div>;
}
export default function ProfilePage({ userId }: { userId: string }) {
return (
<div>
{/* Tez qism — darrov (Suspense'siz): */}
<Suspense fallback={<HeaderSkeleton />}>
<ProfileHeader userId={userId} />
</Suspense>
{/* Sekin qism — alohida stream (header'ni kutMAYDI): */}
<Suspense fallback={<StatsSkeleton />}>
<ProfileStats userId={userId} />
</Suspense>
</div>
);
}Bu kod nima qiladi: Bu — streaming + kesh bilan eng tez yuklanish (13.4: 2.8 streaming + 2.3 kesh — birga). Sahifada ikki qism: ProfileHeader (asosiy — user nomi — tez API, 60 soniya keshlangan — revalidate: 60) va ProfileStats (tahlil — sekin API, keshlanmagan — no-store — har so'rov yangi). Har biri alohida <Suspense> bilan o'ralgan — bu streaming (13.4: 2.8): har qism mustaqil yuklanadi (biri ikkinchisini kutmaydi). Natijada: header (tez) darrov ko'rinadi (skeleton'dan keyin), stats (sekin) keyinroq stream bo'lib keladi (header'ni kutmacdan). Agar ikkalasini bitta await bilan olsak (Suspense'siz), butun sahifa eng sekin qism (stats)ni kutardi — header ham kech ko'rinardi. Suspense bilan — har qism o'z tezligida (header darrov, stats keyin). Bundan tashqari, har qism mos kesh bilan (ProfileHeader — 60 soniya kesh, chunki user nomi kam o'zgaradi; ProfileStats — kesh yo'q, chunki statistika jonli). Demak bu misol uch texnikani birlashtiradi: (1) streaming (Suspense — qismlar mustaqil — tez idrok); (2) mos kesh (har ma'lumot o'z strategiyasi — 2.3); (3) kod tashkili (har qism alohida async komponent). Bu — performance'ning "qatlamli" yondashuvi: kesh (ma'lumot tez), streaming (qismlar mustaqil), Server Components (kam JS). Birga — eng tez idrok etilgan sahifa (foydalanuvchi asosiy kontentni darrov ko'radi, qolgani keladi). Eng tez ilova — bir texnika emas, balki ularning birikmasi.
Misol 7 — Bundle tahlili va optimizatsiya (2.10)
Maqsad: Katta bundle'ni topib optimizatsiya qilish — bundle analyzer bilan. Bu "nega sayt sekin?" savolining amaliy javobi.
// next.config.js — bundle analyzer sozlash:
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
module.exports = withBundleAnalyzer({ /* ... */ });
// Ishga tushirish: ANALYZE=true npm run build
// brauzep'da bundle xaritasi ochiladi (qaysi paket qancha joy egallaydi)
// TOPILGAN MUAMMOLAR va YECHIM:
// moment.js (katta — 70KB) date-fns (kichik — kerakli qism) yoki native Intl
// lodash to'liq import import faqat kerakli: import debounce from "lodash/debounce"
// og'ir grafik har sahifada next/dynamic (lazy — Misol 5)
// katta ikon kutubxonasi faqat kerakli ikonlar (tree-shaking)Bu kod nima qiladi: Bu — bundle tahlili (sayt sekinligining sababini topish — 2.10). Bundle — brauzerga yuboriladigan JavaScript (qancha katta bo'lsa, shuncha sekin yuklanadi). @next/bundle-analyzer — bundle'ni vizualizatsiya qiladi (qaysi paket/modul qancha joy egallaydi — interaktiv xarita). Sozlash: next.config.jsda withBundleAnalyzer o'rab, ANALYZE=true npm run build bilan ishga tushiriladi — brauzer'da bundle xaritasi ochiladi (har paket qancha KB ko'rsatiladi). Topiladigan keng muammolar va yechim: (1) moment.js (sana kutubxonasi — 70KB — katta, butun tillar bilan) date-fns (kichik, faqat kerakli funksiya) yoki native Intl (brauzer o'rnatilgan — 0KB); (2) lodash to'liq import (import _ from "lodash" — butun kutubxona) faqat keraklisini (import debounce from "lodash/debounce" — faqat o'sha funksiya); (3) og'ir grafik har sahifada next/dynamic (lazy — Misol 5); (4) katta ikon kutubxonasi (butun import) faqat kerakli ikonlar (tree-shaking — ishlatilmagan kod olib tashlanadi). Demak: bundle analyzer — "nega sayt sekin?" savolining diagnostikasi (qaysi paket og'ir ekanini ko'rsatadi), keyin har og'ir paketni optimizatsiya qilasiz (kichik muqobil, qisman import, lazy load). Bu — performance optimizatsiyasining o'lchovli yondashuvi (taxmin emas — o'lchab, eng katta muammoni topib, tuzatish). Professional ilovada bundle hajmi kuzatiladi (har yangi paket bundle'ga qancha qo'shadi?). Kichik bundle — tez yuklanish (LCP, INP — 2.9). "O'lchasangiz — boshqara olasiz."
Misol 8 — Metadata va SEO performance (2.9, 13.8 ko'prik)
Maqsad: Sahifa metadata'sini server'da generatsiya qilish (SEO + ijtimoiy ulashish) — performance'ga ta'sir qilmasdan. Bu 13.8 ko'prigi va Core Web Vitals bilan bog'liq.
// app/blog/[slug]/page.tsx — metadata server'da (qo'shimcha JS yo'q)
import type { Metadata } from "next";
// Metadata server'da generatsiya (HTML <head>'ga — brauzepga JS qo'shmaydi):
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const post = await fetch(`/api/posts/${slug}`, { next: { revalidate: 3600 } }).then((r) => r.json());
return {
title: post.title, // <title> (SEO)
description: post.excerpt, // <meta description>
openGraph: { // ijtimoiy ulashish (Facebook, Telegram)
title: post.title,
images: [{ url: post.coverImage }], // ulashganda ko'rinadigan rasm
},
};
}
export default async function BlogPostPage({ params }: { params: Promise<{ slug: string }> }) {
// ... sahifa kontenti
}Bu kod nima qiladi: Bu — metadata server'da generatsiya (SEO + performance — 2.9, 13.8 ko'prik). generateMetadata — Next.js'ning maxsus funksiyasi: sahifa metadata'sini (<title>, <meta> teglari) server'da dinamik generatsiya qiladi. Bu yerda blog post uchun: title (<title> — Google qidiruvda ko'rsatadigan sarlavha — SEO), description (<meta description> — qidiruvdagi qisqa tavsif), openGraph (ijtimoiy tarmoqda — Facebook, Telegram, Twitter — ulashganda ko'rinadigan sarlavha va rasm — link ko'rinishi). Eng muhim — bu metadata server'da generatsiya bo'ladi va to'g'ridan HTML <head>ga qo'shiladi (brauzerga qo'shimcha JavaScript yo'q — performance'ga ta'sir qilmaydi — faqat HTML). SPA'da (11-QISM) metadata client'da (useEffect bilan document.title — 11.5) o'zgartiriladi — bu sekin (JavaScript yuklanguncha metadata yo'q) va Google ko'rmasdi (qidiruv roboti JavaScript'ni kutmaydi). Next.js'da metadata HTML ichida (server'da) — Google darrov ko'radi (SEO), ijtimoiy ulashish ishlaydi, va JavaScript qo'shilmaydi (performance saqlanadi). revalidate: 3600 — metadata ham keshlanadi (post o'zgarmasa qayta olinadi). Demak: SEO (Google ko'radi) + ijtimoiy (link chiroyli ulashiladi) + performance (HTML, JS yo'q) — uchalasi. Bu 13.8 (Metadata va SEO)da chuqur ochiladi — bu yerda uning performance tomoni ko'rsatildi (server metadata — qo'shimcha yuk yo'q). Metadata — SEO va ulashish uchun muhim, va Next.js uni performance'ga ziyon yetkazmacdan beradi.
Misol 9 — Kesh muammosini debug qilish (2.5, 2.6)
Maqsad: "O'zgartirdim, lekin ko'rinmaydi" muammosini tashxis va tuzatish — eng keng Next.js kesh chalkashligi. Bu amaliy debugging mahorati.
// MUAMMO: Server Action mahsulotni o'zgartirdi, lekin sahifada eski narx ko'rinadi
// NOTO'G'RI — revalidate yo'q (kesh eski qoladi):
"use server";
export async function updatePrice(id: string, price: number) {
await db.product.update({ where: { id }, data: { price } });
// revalidate YO'Q Data Cache + Full Route Cache + Router Cache ESKI qoladi!
}
// TO'G'RI — barcha kesh qatlamini yangila:
"use server";
import { revalidatePath, revalidateTag } from "next/cache";
export async function updatePrice(id: string, price: number) {
await db.product.update({ where: { id }, data: { price } });
revalidateTag("products"); // 1. Data Cache (teg bilan — Misol 2)
revalidatePath(`/products/${id}`); // 2. Full Route Cache + Router Cache (bu sahifa)
revalidatePath("/products"); // 3. ro'yxat sahifasi ham
// endi barcha qatlam yangilandi (yangi narx ko'rinadi)
}Bu kod nima qiladi: Bu — eng keng Next.js kesh muammosining tashxisi va yechimi (2.5, 2.6 — "o'zgardi, lekin ko'rinmaydi"). Muammo: Server Action mahsulot narxini DB'da o'zgartirdi, lekin foydalanuvchi sahifada eski narxni ko'radi. Sababi: DB o'zgardi, lekin kesh qatlamlari (Data Cache — fetch natija, Full Route Cache — sahifa HTML, Router Cache — client) hali eski ma'lumotni saqlab turibdi 2.1-bob. Mutation DB'ni o'zgartiradi, lekin keshni avtomatik yangilamaydi (Next.js keshni — tezlik uchun — saqlab turadi, qachon yangilashni siz aytishingiz kerak). Noto'g'ri kod — revalidate yo'q (DB o'zgardi, lekin kesh eski — eski narx ko'rinadi). To'g'ri kod — mutation'dan keyin barcha tegishli keshni yangilash: (1) revalidateTag("products") — Data Cache (fetch natija — "products" tegli — Misol 2); (2) revalidatePath(\/products/${id}`)— Full Route Cache (sahifa HTML) + Router Cache (client) — bu mahsulot sahifasi; (3)revalidatePath("/products")— ro'yxat sahifasi ham (u yerda ham narx ko'rinadi). Endi barcha qatlam yangilandi — foydalanuvchi yangi narxni ko'radi. **Debugging mantiqi**: "o'zgardi, lekin ko'rinmaydi" holatida — "qaysi kesh qatlami eski?" deb o'ylab ko'rish kerak (Data — fetch keshlanganmi? Full Route — sahifa statikmi? Router — client navigatsiya?), keyin mosrevalidate` (Tag — Data; Path — Full Route + Router). Bu — Next.js bilan ishlaganda eng tez-tez uchraydigan muammo (deyarli har yangi loyihada), va uning yechimi har doim bir xil: mutation'dan keyin revalidate (to'g'ri qatlamni). Kesh qatlamlarini 2.1-bob tushunish bu muammoni darrov hal qilishga yordam beradi.
Misol 10 — To'liq optimizatsiyalangan sahifa (hammasi birga)
Maqsad: Barcha optimizatsiyani bir sahifada birlashtirish — image, font, kesh, Server Components, lazy, streaming. Bu butun bobning amaliy yakuni.
// app/products/[id]/page.tsx — to'liq optimizatsiyalangan
import Image from "next/image";
import { Suspense } from "react";
import dynamic from "next/dynamic";
const Reviews = dynamic(() => import("./Reviews")); // og'ir — lazy (2.10)
export const revalidate = 3600; // ISR — statik tezlik + soatlik yangilanish (2.6)
export default async function ProductPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
// Kesh bilan ma'lumot (Data Cache — 2.3):
const product = await fetch(`/api/products/${id}`, { next: { tags: [`product-${id}`] } }).then((r) => r.json());
return (
<main>
{/* Optimizatsiyalangan rasm (LCP — 2.7): */}
<Image src={product.image} width={800} height={600} alt={product.name} priority />
{/* Server'da render (kam JS — 2.1, 13.3): */}
<h1>{product.name}</h1>
<p>{product.price} so'm</p>
{/* Interaktiv qism — Client (faqat shu — 13.3: 2.6): */}
<AddToCartButton productId={product.id} />
{/* Sekin qism — streaming (2.6, 13.4: 2.8): */}
<Suspense fallback={<ReviewsSkeleton />}>
<Reviews productId={product.id} /> {/* lazy + Suspense */}
</Suspense>
</main>
);
}Bu kod nima qiladi: Bu — butun bobning amaliy yakuni (barcha optimizatsiya bir sahifada birga). Har texnika o'z o'rnida: (1) ISR (export const revalidate = 3600) — sahifa statik (tez — Full Route Cache — 2.4), lekin soatlik yangilanadi 2.6-bob — statik tezlik + yangilik; (2) Data Cache + teg (fetch(..., { next: { tags: [\product-${id}`] } })) — ma'lumot keshlangan 2.3-bob, teg bilan (admin o'zgartirsa revalidateTag— darrov — Misol 2); (3) **next/image priority** — asosiy rasm optimizatsiyalangan (WebP, responsive, LCP tez, CLS yo'q — 2.7); (4) **Server Components** — sarlavha/narx server'da render (kam JavaScript brauzerga — 13.3, 2.1 — tez INP); (5) **minimal Client** — faqatAddToCartButtonClient (interaktiv barg — 13.3: 2.6 —"use client"pastda); (6) **lazy + streaming** —Reviews(og'ir izohlar bo'limi)next/dynamicbilan lazy 2.10-bob **va**
Misol 11 — DB so'rovini keshlash (unstable_cache — 2.12)
Maqsad: ORM (Prisma) orqali DB so'rovini keshlash — fetch bo'lmagani uchun unstable_cache bilan. Bu DB'li ilovada (fetch keshi ishlamaganda) kesh olishning asosiy usuli.
// lib/products.ts — DB so'rovini keshlash (fetch EMAS — ORM)
import { unstable_cache } from "next/cache";
import { db } from "@/lib/db";
// Doimiy Data Cache (so'rovlar aro — 1 soat + teg):
export const getProducts = unstable_cache(
async () => {
return db.product.findMany({ orderBy: { createdAt: "desc" } });
},
["products-list"], // kesh kaliti (bir xil kalit — bir xil kesh)
{ revalidate: 3600, tags: ["products"] }, // 1 soat + "products" teg
);
// Server Action'da o'zgartirilganda — teg bilan yangilash (Misol 2):
// revalidateTag("products") getProducts keshini ham yangilaydiBu kod nima qiladi: Bu — DB so'rovini keshlash (fetch emas — ORM — 2.12). Muammo: fetch keshi (Data Cache — 2.3) faqat fetch uchun ishlaydi, lekin Prisma/Drizzle kabi ORM'lar DB'ga to'g'ridan boradi (fetch ishlatmaydi) — shuning uchun ular avtomatik keshlanmaydi (har so'rovda DB'ga boradi — sekin, DB yuki katta). Yechim — unstable_cache: DB so'rovini o'rab, uni Data Cache'ga qo'yadi. Uch argument: (1) funksiya (async () => db.product.findMany() — keshlanadigan DB so'rovi); (2) kesh kaliti (["products-list"] — bu kalit bo'yicha kesh saqlanadi va topiladi — bir xil kalit bir xil natijani beradi); (3) opsiyalar ({ revalidate: 3600, tags: ["products"] } — 1 soat keshda, "products" tegli — revalidateTag("products") uni ham yangilaydi). Natija: getProducts() birinchi chaqirilganda DB'ga boradi va natijani keshlaydi, keyingi so'rovlar (1 soat davomida) keshdan oladi (DB'ga bormaydi — tez, DB yuki kam) — xuddi fetch keshiday, lekin ORM uchun. tags bilan — admin mahsulot qo'shsa/o'zgartirsa revalidateTag("products") (Server Action'da — Misol 2) bu keshni darrov yangilaydi (on-demand). Qachon kerak: DB bilan to'g'ridan ishlaganda (Prisma, Drizzle, DB drayveri — fetch'siz — 13.9), kesh olish uchun. Diqqat: unstable_cache ichida cookies()/headers() (dinamik funksiya — 2.11) ishlatib bo'lmaydi (kesh statik bo'lishi kerak — foydalanuvchiga xos bo'lmasin). Demak: fetch bor bo'lsa — fetch keshi 2.3-bob; ORM/DB to'g'ridan bo'lsa — unstable_cache 2.12-bob. Ikkalasi bir xil Data Cache qatlamiga tushadi 2.1-bob va bir xil revalidateTag/revalidatePath bilan boshqariladi.
Misol 12 — Core Web Vitals o'lchash (useReportWebVitals — 2.9)
Maqsad: Real foydalanuvchilardan Core Web Vitals (LCP/CLS/INP)ni yig'ish — useReportWebVitals bilan. Bu "sayt real foydalanuvchida qanchalik tez?" savolining o'lchovli javobi.
// app/_components/WebVitals.tsx — real foydalanuvchi metrikasini yig'ish
"use client";
import { useReportWebVitals } from "next/web-vitals";
export function WebVitals() {
useReportWebVitals((metric) => {
// metric: { name: "LCP" | "CLS" | "INP" | ..., value, id, rating }
// Analitikaga yuborish (masalan o'z endpoint yoki analytics):
const body = JSON.stringify(metric);
navigator.sendBeacon?.("/api/vitals", body); // sahifani bloklamasdan yuborish
if (process.env.NODE_ENV === "development") {
console.log(metric.name, Math.round(metric.value), metric.rating);
}
});
return null; // UI yo'q — faqat o'lchov
}
// app/layout.tsx ichida: <WebVitals /> (bir marta — butun ilova uchun)Bu kod nima qiladi: Bu — real foydalanuvchilardan Core Web Vitals o'lchash 2.9-bob. Muammo: Lighthouse/PageSpeed 2.9-bob — laboratoriya sinovi (bir marta, sizning qurilmangizda) — lekin real foydalanuvchilar turli qurilma, turli tarmoqda (sekin telefon, zaif internet) — ularning haqiqiy tajribasi boshqacha bo'lishi mumkin. Yechim — useReportWebVitals (next/web-vitals'dan): har real foydalanuvchi sahifasida Core Web Vitals metrikasini o'lchaydi va sizga beradi (metric obyektida name — LCP/CLS/INP, value — qiymat, rating — "good"/"needs-improvement"/"poor"). Bu misol: metrikani navigator.sendBeacon bilan /api/vitals endpoint'ga yuboradi (sendBeacon — sahifani bloklamasdan ma'lumot yuboradi, hatto sahifa yopilsa ham), development'da esa konsolga chiqaradi (darhol ko'rish uchun). WebVitals komponenti "use client" (metrika brauzerda o'lchanadi) va UI qaytarmaydi (return null — faqat o'lchov). U layout.tsxda bir marta qo'yiladi (butun ilova uchun). Natija: real foydalanuvchilardan dala ma'lumoti (field data) yig'iladi — "sayt haqiqatda qanchalik tez?" (Vercel Speed Insights — 2.13 — buni tayyor qiladi, lekin useReportWebVitals bilan o'z analitikangizga ham yuborishingiz mumkin). Nega muhim: performance — bir marta o'lchab qo'yiladigan emas, doimiy kuzatiladigan narsa (yangi kod Web Vitals'ni yomonlashtirdimi? qaysi sahifa sekin?). Laboratoriya (Lighthouse) + dala (useReportWebVitals/Speed Insights) — birga to'liq rasm. "O'lchamasangiz — boshqara olmaysiz" (Misol 7 bundle bilan bir tamoyil — o'lchovga asoslangan optimizatsiya).
5. To'g'ri va noto'g'ri holatlar
1) Mutation'dan keyin
revalidate yo'q (kesh eski — "o'zgardi, ko'rinmaydi" — 2.5)
revalidatePath/Tag (kesh yangila — Misol 9)2) Rasm
<img> (optimizatsiya yo'q — og'ir, CLS — 2.7)
next/image (format, lazy, CLS yo'q — Misol 3)3) LCP rasmi
asosiy rasmga priority yo'q (lazy — LCP sekin)
priority (darrov — LCP tez — 2.9, Misol 3)4) Og'ir komponent
og'ir grafik to'g'ridan import (boshlang'ich bundle katta)
next/dynamic (lazy — Misol 5)5) Shrift
<link fonts.googleapis> (Google so'rov, CLS — 2.8)
next/font (self-hosted, CLS yo'q — Misol 4)6) Kesh strategiyasi
hamma fetch bir xil (jonli ma'lumot ham keshlangan — eski)
har ma'lumot o'z strategiyasi (force-cache/revalidate/no-store — Misol 1)7) DB so'rovi (ORM)
har render'da db.findMany (kesh yo'q — DB yuki katta — 2.12)
unstable_cache(fn, keys, { revalidate, tags }) (Data Cache — Misol 11)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — "O'zgartirdim, lekin eski ko'rinadi"
Sababi: mutation'dan keyin revalidate yo'q (Data/Full Route/Router Cache eski — 2.5). Yechimi: revalidatePath/Tag (barcha qatlam — Misol 9).
Xato 2 — Sahifa sekin (katta bundle)
Sababi: og'ir paket boshlang'ich bundle'da 2.10-bob. Yechimi: bundle analyzer + lazy/qisman import (Misol 7).
Xato 3 — Layout sakraydi (CLS yomon)
Sababi: rasm width/height yo'q yoki shrift optimizatsiyasiz 2.9-bob. Yechimi: next/image (width/height) + next/font (Misol 3, 4).
Xato 4 — LCP sekin (asosiy rasm kech)
Sababi: LCP rasmga priority yo'q 2.9-bob. Yechimi: asosiy rasmga priority (Misol 3).
Xato 5 — Next.js 15: ma'lumot keshlanmayapti (kutgandek)
Sababi: Next.js 15 default keshlamaydi 2.3-bob. Yechimi: cache: "force-cache" yoki revalidate (13.4: 2.7).
Xato 6 — Hydration yoki "window is not defined" (dynamic)
Sababi: brauzer-only komponent SSR'da 2.10-bob. Yechimi: next/dynamic ssr: false (Misol 5).
Xato 7 — Router Cache eski (navigatsiyada)
Sababi: client navigatsiya keshda eski 2.5-bob. Yechimi: router.refresh() yoki revalidatePath (mutation'dan keyin).
Xato 8 — Next.js 14 15 ko'chirishda kesh yo'qoldi
Sababi: 15'da fetch/GET Route default keshlanmaydi 2.11-bob. Yechimi: oshkor cache: "force-cache" yoki revalidate qo'shish.
Xato 9 — ORM (Prisma) so'rovi har render'da DB'ga boradi
Sababi: fetch keshi ORM'ga ta'sir qilmaydi 2.12-bob. Yechimi: unstable_cache yoki React cache() (Misol 11).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Rendering 13.4-bob: Full Route Cache — SSG/ISR; Data Cache — fetch strategiyalari.
- Data fetching 13.5-bob: Request Memoization, revalidate (mutation'dan keyin).
- Server Components 13.3-bob: kam JS — INP yaxshi; render kesh.
- Route Handlers 13.6-bob: kesh (revalidate); Next.js 15 GET default uncached 2.11-bob; middleware (header — performance).
- SEO 13.8-bob: Core Web Vitals — Google reyting; metadata performance.
- Code splitting 11.8-bob: next/dynamic — React.lazy versiyasi.
- Database 13.9-bob: unstable_cache / React cache — ORM so'rovini keshlash 2.12-bob.
- Deploy 13.11-bob: CDN, edge — kesh global; PPR, Speed Insights, Vercel optimizatsiya 2.13-bob.
- Images/Forms: next/image — har sahifada.
8. Eng yaxshi amaliyotlar (best practices)
- Mutation'dan keyin revalidate (eng keng xato — 2.5, Misol 9).
- next/image har rasmga (LCP rasmga priority — 2.7, Misol 3).
- next/font shriftga (CLS yo'q — 2.8, Misol 4).
- Har ma'lumot o'z kesh strategiyasi (force-cache/revalidate/no-store — Misol 1).
- Teg-asosli revalidation (bir o'zgarish ko'p sahifa — Misol 2).
- next/dynamic og'ir komponentga (lazy — Misol 5).
- Server Components default (kam JS — INP — 13.3).
- Streaming sekin qismga (Suspense — Misol 6).
- Bundle tahlil (katta paketni top — Misol 7).
- Core Web Vitals o'lcha (LCP/CLS/INP — Lighthouse + real foydalanuvchi — 2.9, Misol 12).
- ORM so'rovini keshlash (unstable_cache / React cache — DB'da — 2.12, Misol 11).
- Next.js 15 default'ini bil (fetch/GET uncached — oshkor keshla — 2.11).
9. Amaliy loyiha: "Optimizatsiyalangan E-commerce Sahifa"
Kesh va performance optimizatsiyasini real sahifada mustahkamlash.
Maqsad
Mahsulot sahifani maksimal optimizatsiya: kesh strategiyalari, image, font, lazy, streaming, Core Web Vitals.
Talablar (requirements)
- Kesh strategiyalari: kategoriya (force-cache), mahsulot (revalidate+teg), zaxira (no-store) — Misol 1.
- On-demand revalidation: admin o'zgartirsa teg bilan (Misol 2).
- next/image: asosiy (priority) + galereya (lazy) — Misol 3.
- next/font: self-hosted shrift (Misol 4).
- next/dynamic: og'ir komponent lazy (izohlar/grafik — Misol 5).
- Streaming: sekin qism Suspense (Misol 6).
- Server Components: kam JS (interaktiv qism minimal — 13.3).
- Bundle tahlil: katta paketni top va optimizatsiya (Misol 7).
- Core Web Vitals: Lighthouse'da +
useReportWebVitalsbilan real o'lcha (LCP/CLS/INP — 2.9, Misol 12). - Kesh debug: "o'zgarish ko'rinmasa" revalidate (Misol 9).
- DB kesh: ORM so'rovini
unstable_cachebilan keshla (Misol 11).
Maslahatlar (hint)
- Har ma'lumot o'z kesh strategiyasi (Misol 1).
- LCP rasmga priority (Xato 4).
- Mutation'dan keyin revalidate (Xato 1).
- Og'ir komponent lazy (Xato 2).
- next/font CLS'dan (Xato 3).
- Bundle analyzer bilan o'lcha (taxmin emas — Misol 7).
"Tayyor" mezonlari (acceptance criteria)
- Kesh strategiyalari (3 xil).
- On-demand revalidation (teg).
- next/image (priority + lazy).
- next/font (self-hosted).
- next/dynamic (lazy).
- Streaming (Suspense).
- Core Web Vitals yaxshi (LCP<2.5s, CLS<0.1, INP<200ms).
- Kesh muammosi yo'q (revalidate to'g'ri).
- ORM so'rovi keshlangan (unstable_cache — DB yuki kam).
- Real Web Vitals yig'iladi (useReportWebVitals).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda Next.js caching va performance'ni chuqur o'rgandik:
- 4 kesh qatlami 2.1-bob; Request Memoization 2.2-bob; Data Cache 2.3-bob; Full Route Cache 2.4-bob; Router Cache 2.5-bob; boshqarish (revalidate/tags — 2.6).
- next/image 2.7-bob; next/font, next/script 2.8-bob; Core Web Vitals 2.9-bob; lazy/prefetch/best practices 2.10-bob.
- Next.js 15 kesh o'zgarishlari va "use cache" 2.11-bob; unstable_cache, React cache, staleTimes 2.12-bob; Partial Prerendering, @next/third-parties, edge/CDN 2.13-bob.
Endi siz Next.js'ning tezligi ortidagi kesh qatlamlarini (va "nega eskirgan?" muammosini) tushunasiz, hamda ilovangizni optimizatsiya qila olasiz (image, font, lazy, streaming, kesh) — Core Web Vitals'ni yaxshilab, SEO va UX'ni oshirasiz.
Keyingi bob — 13.8-bob: Metadata, SEO va Optimizatsiya. Performance'ni bildik; endi SEO (qidiruv tizimida topilish)ni chuqur ko'ramiz: Metadata API (metadata, generateMetadata — title, description, Open Graph), sitemap va robots.txt (qidiruv robotlari uchun), strukturali ma'lumot (JSON-LD — boy natijalar), ijtimoiy ulashish (Open Graph, Twitter Card), va SEO best practices (semantik HTML, canonical, til). Bu — saytni Google va ijtimoiy tarmoqlarda ko'rinadigan qilishning kaliti.
Foydalanilgan rasmiy/ishonchli manbalar
- Next.js rasmiy hujjati — "Caching in Next.js" (Request Memoization, Data Cache, Full Route Cache, Router Cache)
- Next.js hujjati —
revalidatePath,revalidateTag,unstable_cache; Reactcache() - Next.js hujjati —
next/image,next/font,next/script,next/dynamic;useReportWebVitals - Next.js hujjati — Next.js 15 kesh o'zgarishlari (caching defaults),
"use cache"direktivasi, Partial Prerendering (PPR) - Next.js hujjati —
staleTimes(Router Cache sozlash),@next/third-parties - web.dev — Core Web Vitals (LCP, CLS, INP), image va font optimizatsiya bo'yicha yo'riqnomalar
- Vercel — Bundle analysis (
@next/bundle-analyzer), Speed Insights, edge/CDN kesh
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!