WisarWisar
Dasturlash kitobi/13-QISM — NextJS53 daqiqa

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)

text
  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) — fetch natijasini 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)

text
  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 Memoizationbir 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 GET fetch (bir xil URL + opsiya); (3) avtomatik (React fetchni o'rab keshlaydi — sozlash kerak emas); (4) DB so'rov uchun — React cache() (fetch emas — 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)

text
  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 Cachefetch natijasini doimiy saqlaydi (Request Memoization'dan farqli — render tugasa ham qoladi, so'rovlar va hatto deploylar orasida). fetch opsiyalari 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-cache yoki revalidate kerak — 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)

text
  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 Cachestatik sahifaning to'liq HTMLini (va RSC payload'ini) saqlaydi (build paytida generatsiya — 13.4: 2.4 SSG'ning kesh tomoni). Misol: app/blog/page.tsx statik 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/revalidateTag yoki 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)

text
  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 Cachebrauzer'da (client) tashrif buyurilgan sahifalar natijasini (RSC payload) saqlaydi — client navigatsiya tez bo'lishi uchun. Misol: foydalanuvchi /products /about /products (qaytsa) — birinchi marta /products server'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'da revalidatePath Router 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 keyin revalidate (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)

text
  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 } }) yoki export 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), keyin revalidateTag("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 yetadi revalidate: 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)

text
  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/muhim

Rasm optimizatsiyasi (next/image) — performance'ning eng katta g'alabasi (rasm — har saytning eng og'ir qismi). next/image (Image komponenti) — 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'qwidth/height bilan 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)

text
  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 qismlari

Shrift 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/image 2.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)

text
  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 priority 2.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

text
  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.8 React.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

text
  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 fetch default 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" }) yoki next: { 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 funksiyalarcookies()/headers() chaqirilsa, sahifa avtomatik dinamik bo'ladi (chunki javob har foydalanuvchiga xos — keshlanmaydi). Ikki nuqta: (1) Next.js 15 default uncached (fetch/GET Route — oshkor force-cache/revalidate kerak — 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

text
  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 muddatini next.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) React cache()fetch emas, 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'da getUser(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, tagsrevalidateTag ishlashi uchun). Ikki nuqta: (1) React cache() — 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: fetch keshi 2.3-bob faqat fetch uchun — Prisma/Drizzle kabi ORM'lar DB'ga to'g'ridan boradi (fetch emas), shuning uchun ularni keshlash uchun cache() (bir render) yoki unstable_cache() (doimiy) ishlatiladi. Demak DB'li ilovada 13.9-bob kesh — unstable_cache orqali (fetch keshi ishlamaydi). Bu — kesh qatlamlarini (2.1) fetch'siz ma'lumot manbalariga (DB, ORM) kengaytirish.

2.13. Partial Prerendering, third-parties va edge/CDN

text
  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 tez

Partial 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 = true bilan 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" /> — bu next/script 2.8-bob ustiga qurilgan, tayyor va optimizatsiyalangan komponentlar (strategy qo'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

text
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.

tsx
// 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) kategoriyalarcache: "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) mahsulotlarnext: { 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.

tsx
// 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 yangilaydi

Bu 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.

tsx
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 EMASdarrov2.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 yuklanadiboshlang'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.

tsx
// 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.

tsx
// 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.

tsx
// 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.

tsx
// 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.

tsx
// 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.

tsx
// 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 kodrevalidate 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.

tsx
// 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**` bilan streaming (asosiy kontentni kutmaydi — 13.4: 2.8). Natija — eng tez sahifa: statik HTML (darrov ko'rinadi), optimizatsiyalangan rasm (LCP tez), kam JavaScript (Server Components — INP tez), CLS yo'q (image/font o'lcham), izohlar keyinroq (streaming + lazy — boshlang'ich yuk kam), kesh to'g'ri (revalidate). Bu — Next.js performance'ning to'liq ko'rinishi: har optimizatsiya texnikasi (kesh, image, Server Components, lazy, streaming) birga ishlab, Core Web Vitals (LCP/CLS/INP — 2.9)ni maksimal yaxshilaydi. Bir texnika emas — birikma. Bu sahifa Google'da yuqori (tez — SEO), foydalanuvchi qoladi (silliq — UX), va arzon (kesh — kam server yuki). Professional Next.js sahifasi shunday quriladi — har element ongli optimizatsiya bilan.

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.

ts
// 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 yangilaydi

Bu 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.

tsx
// 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-boblaboratoriya 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

text
 revalidate yo'q (kesh eski — "o'zgardi, ko'rinmaydi" — 2.5)
 revalidatePath/Tag (kesh yangila — Misol 9)

2) Rasm

text
 <img> (optimizatsiya yo'q — og'ir, CLS — 2.7)
 next/image (format, lazy, CLS yo'q — Misol 3)

3) LCP rasmi

text
 asosiy rasmga priority yo'q (lazy — LCP sekin)
 priority (darrov — LCP tez — 2.9, Misol 3)

4) Og'ir komponent

text
 og'ir grafik to'g'ridan import (boshlang'ich bundle katta)
 next/dynamic (lazy — Misol 5)

5) Shrift

text
 <link fonts.googleapis> (Google so'rov, CLS — 2.8)
 next/font (self-hosted, CLS yo'q — Misol 4)

6) Kesh strategiyasi

text
 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)

text
 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)

  1. Kesh strategiyalari: kategoriya (force-cache), mahsulot (revalidate+teg), zaxira (no-store) — Misol 1.
  2. On-demand revalidation: admin o'zgartirsa teg bilan (Misol 2).
  3. next/image: asosiy (priority) + galereya (lazy) — Misol 3.
  4. next/font: self-hosted shrift (Misol 4).
  5. next/dynamic: og'ir komponent lazy (izohlar/grafik — Misol 5).
  6. Streaming: sekin qism Suspense (Misol 6).
  7. Server Components: kam JS (interaktiv qism minimal — 13.3).
  8. Bundle tahlil: katta paketni top va optimizatsiya (Misol 7).
  9. Core Web Vitals: Lighthouse'da + useReportWebVitals bilan real o'lcha (LCP/CLS/INP — 2.9, Misol 12).
  10. Kesh debug: "o'zgarish ko'rinmasa" revalidate (Misol 9).
  11. DB kesh: ORM so'rovini unstable_cache bilan 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; React cache()
  • 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!
13.7-bob: Caching va Performance — Wisar