WisarWisar
Dasturlash kitobi/13-QISM — NextJS42 daqiqa

13.2-bob: App Router va file-based routing

13-QISM — Next.js · 2-mavzu


1. Kirish va motivatsiya

13.1-bobda Next.js'ning fayl-asosli routing'i bilan tanishdik — app/products/page.tsx avtomatik /products bo'ladi. Endi shu routing'ni chuqur o'rganamiz: dinamik yo'llar (/products/42 — har mahsulot uchun), nested layouts (har bo'lim o'z karkasi), route groups (URL'ni o'zgartirmasdan fayllarni guruhlash), navigatsiya (<Link>, useRouter, redirect), va maxsus fayllar (loading, error, not-found). Bu — Next.js ilovasining skeletini tashkil qiladi, va u React Router'dan 11.9-bob ancha kuchliroq va deklarativroq.

App Router'ning markaziy g'oyasi — konvensiya orqali routing (configuration over convention'ning teskarisi): siz routing'ni kod bilan sozlamaysiz (React Router'dagi <Routes>, <Route> massivlari — 11.9 — yo'q), balki papka va fayl strukturasi routing'ni belgilaydi. app/ papkacidagi har papka — URL segmenti, har page.tsx — sahifa, har layout.tsx — o'rovchi. Bu juda kuchli: routing "jonli xarita" bo'ladi (papkani ko'rib URL'ni bilasiz), nested layout tabiiy (papka ichida papka), va maxsus fayllar (loading/error) avtomatik ishlaydi. Bundan tashqari, App Router Server Components bilan ishlaydi (default — 13.3), shuning uchun routing va ma'lumot olish chambarchas bog'liq.

Bu bob: fayl-asosli routing (page/folder — chuqur), dinamik segmentlar ([id], [...slug] — catch-all, [[...slug]] — optional), params (sahifa dinamik qiymatni qanday oladi), nested layouts (ko'p qatlamli — har bo'lim o'z layout'i), route groups ((group) — URL'siz guruhlash), private papkalar (_folder), navigatsiya (<Link>, useRouter, redirect, usePathname), maxsus fayllar (loading/error/not-found — konvensiya), parallel/intercepting routes (ilg'or — qisqa), va generateStaticParams (dinamik SSG — 13.4 ko'prik). Har bir mavzu to'liq, har kod misolida maqsad + izoh + "nima qiladi" bilan ochiladi.

O'xshatish: App Router — bu bino qavatlar rejasi (blueprint). React Router 11.9-bob — bu qo'lda yozilgan manzillar ro'yxati (/products ProductPage, /about AboutPage — har birini qog'ozga yozasiz). App Router — bu binoning o'zi qavatlar rejasi: har xona (papka) o'z manziliga ega (URL), xona ichidagi "asosiy jihoz" (page.tsx) — o'sha xonaning mazmuni, va har qavat (papka) o'z umumiy koridori va lift'iga (layout.tsx) ega bo'lishi mumkin. Siz alohida manzillar ro'yxatini saqlamaysiz — bino strukturasining o'zi manzilni belgilaydi (4-qavat, 12-xona = /floor4/room12). Yangi xona qo'shsangiz — yangi manzil avtomatik paydo bo'ladi. Bu — "kod o'rniga struktura" falsafasi.

Nega muhim?

  • Next.js skeleti — routing har Next.js ilovasining asosi (sahifalar, layout, navigatsiya).
  • Deklarativ va kuchli — fayl strukturasi routing (React Router kodidan ancha sodda va aniq).
  • Nested layouts — murakkab ilova strukturasi (dashboard, ko'p bo'lim) tabiiy.
  • Server Components bilan — routing + ma'lumot olish integratsiyalangan (13.3, 13.5).

2. Nazariya — chuqur tushuntirish

2.1. Fayl-asosli routing (chuqur)

text
  PAPKA STRUKTURASI = URL (App Router — har papka segmenti, page.tsx = sahifa):

  app/
  ├── page.tsx                /                    (bosh sahifa)
  ├── about/page.tsx          /about
  ├── products/
  │   ├── page.tsx            /products            (mahsulotlar ro'yxati)
  │   └── [id]/page.tsx       /products/42         (dinamik — har mahsulot — 2.2)
  ├── blog/
  │   ├── page.tsx            /blog
  │   └── [slug]/page.tsx     /blog/my-post
  └── dashboard/
      ├── layout.tsx          dashboard layout (faqat /dashboard/* uchun — 2.4)
      ├── page.tsx            /dashboard
      └── settings/page.tsx   /dashboard/settings

  ASOSIY QOIDA:
  - PAPKA  URL segmenti (products  /products)
  - page.tsx  sahifa (route'ni "ko'rinadigan" qiladi — page.tsx YO'Q bo'lsa URL ishlamaydi)
  - boshqa fayllar (Button.tsx)  route EMAS (faqat page.tsx route bo'ladi)

   Papka = URL; page.tsx = sahifa (boshqa .tsx fayllar route'ga aylanmaydi — xavfsiz)
   page.tsx YO'Q bo'lsa — papka URL sifatida ishlamaydi (faqat tashkilot)

Fayl-asosli routing — App Router'ning poydevori. Papka strukturasi URL'ni belgilaydi: app/ ichidagi har papka — URL segmenti (products /products), va har papkadagi page.tsx — o'sha yo'lning sahifasi. Misol: app/products/page.tsx /products, app/dashboard/settings/page.tsx /dashboard/settings (papka ichma-ich URL ichma-ich). Asosiy qoida: papka URL segmenti, page.tsx sahifa (route'ni "ko'rinadigan" qiladi). Ikki muhim nuqta: (1) faqat page.tsx (aniq shu nom) route'ga aylanadi — papkadagi boshqa fayllar (Button.tsx, utils.ts) route emas (ular faqat tashkilot/yordamchi — bu xavfsizlik: tasodifan komponent fayli URL bo'lib qolmaydi — React Router'dan farqli, u yerda har narsa qo'lda yoziladi); (2) page.tsx yo'q bo'lsa — papka URL sifatida ishlamaydi (faqat fayllarni guruhlash — masalan app/products/components/ papkasida page.tsx yo'q u URL emas, faqat komponentlar uchun papka). Bu — fayl-routing'ning asosi: papka = yo'l, page.tsx = sahifa, qolgani = tashkilot.

2.2. Dinamik segmentlar — [id], [...slug]

text
  DINAMIK SEGMENT — URL'ning O'ZGARUVCHAN qismi (kvadrat qavs []):

  [id]       bitta dinamik segment:    app/products/[id]/page.tsx  /products/42, /products/abc
  [...slug]  catch-all (ko'p segment): app/docs/[...slug]/page.tsx  /docs/a, /docs/a/b/c
  [[...slug]] optional catch-all:      app/shop/[[...slug]]/page.tsx  /shop, /shop/a, /shop/a/b

  KOMPONENT params'ni oladi (Server Component — props orqali):
  // app/products/[id]/page.tsx
  export default async function ProductPage({ params }) {
    const { id } = await params;        // Next.js 15: params async
    return <h1>Mahsulot {id}</h1>;       // /products/42  id = "42"
  }

  ┌────────────────────────────────────────────────────────────┐
  │ [id]: /products/42 (bitta) | [...slug]: /docs/a/b (ko'p)    │
  │ [[...slug]]: optional (/shop yoki /shop/a) | params: qiymat │
  └────────────────────────────────────────────────────────────┘

   [id] — bitta segment; [...slug] — ko'p (massiv); [[...slug]] — ixtiyoriy ko'p
   params — sahifaga dinamik qiymatni beradi (Next.js 15: async — await params)

Dinamik segmentlar — URL'ning o'zgaruvchan qismlari (kvadrat qavs [] bilan). Uch tur: (1) [id] — bitta dinamik segment: app/products/[id]/page.tsx /products/42, /products/abc (har mahsulot uchun bitta sahifa — 11.9: 2.6 React Router'ning :idiga o'xshaydi); (2) [...slug] — catch-all (ko'p segment): app/docs/[...slug]/page.tsx /docs/a, /docs/a/b/c (slug massiv bo'ladi — ["a", "b", "c"] — docs/wiki kabi ko'p qatlamli yo'l uchun); (3) [[...slug]] — optional catch-all: app/shop/[[...slug]]/page.tsx /shop va /shop/a/b (segment bo'lmasa ham ishlaydi — ixtiyoriy). Komponent dinamik qiymatni params prop orqali oladi (Server Component): export default async function ProductPage({ params }) { const { id } = await params; ... } — Next.js 15'da params async (await params — chunki so'rov ma'lumotlari async — 13.1: 2.10). Ikki nuqta: (1) [id] — bitta segment, [...slug] — ko'p (massiv), [[...slug]] — ixtiyoriy ko'p; (2) params — sahifaga dinamik qiymatni beradi (Next.js 15: await params). Bu — bitta sahifa bilan cheksiz kontent (mahsulot, blog post, foydalanuvchi profili) yaratishning asosi.

2.3. Nested layouts — ko'p qatlamli

text
  NESTED LAYOUTS — har papkada O'Z layout'i (ichma-ich o'raydi — kuchli):

  app/
  ├── layout.tsx              ILDIZ layout (BARCHA sahifani o'raydi — <html><body>)
  └── dashboard/
      ├── layout.tsx          dashboard layout (FAQAT /dashboard/* uchun)
      ├── page.tsx            /dashboard
      └── settings/page.tsx   /dashboard/settings

  /dashboard/settings ochilganda — layoutlar ICHMA-ICH o'raydi:
  ┌─ RootLayout (html/body, navbar) ──────────────┐
  │  ┌─ DashboardLayout (sidebar) ──────────────┐  │
  │  │  ┌─ SettingsPage (kontent) ───────────┐  │  │
  │  │  │  Sozlamalar                         │  │  │
  │  │  └─────────────────────────────────────┘  │  │
  │  └────────────────────────────────────────────┘  │
  └────────────────────────────────────────────────────┘

  ┌────────────────────────────────────────────────────────────┐
  │ Layout'lar ichma-ich (root > dashboard > sahifa)            │
  │ Layout — navigatsiyada SAQLANADI (qayta render bo'lmaydi)   │
  └────────────────────────────────────────────────────────────┘

   Har papka o'z layout.tsx'iga ega bo'lishi mumkin (ichma-ich o'raydi)
   Layout navigatsiyada saqlanadi (sidebar — /dashboard ichida sahifa almashca qayta render yo'q)

Nested layouts — App Router'ning eng kuchli xususiyatlaridan biri. Har papka o'z **layout.tsx**iga ega bo'lishi mumkin, va layoutlar ichma-ich o'raydi. Misol: app/layout.tsx (root — <html>/<body>, umumiy navbar — har sahifani o'raydi) + app/dashboard/layout.tsx (dashboard layout — sidebar — faqat /dashboard/* sahifalari uchun). /dashboard/settings ochilganda, layoutlar ichma-ich o'raydi: RootLayout (navbar) DashboardLayout (sidebar) SettingsPage (kontent) — har biri o'z bo'lagini beradi. (Diqqat: bola sahifa layout'ga children prop orqali keladi.) Bu React Router'ning nested routes + Outlet'iga (11.9: 2.7) o'xshaydi, lekin Next.js'da fayl strukturasi orqali (qo'lda <Outlet> joylashtirish kerak emas — layout.tsx avtomatik bola sahifani children orqali oladi). Ikki muhim nuqta: (1) har papka o'z layout.tsxiga ega bo'lishi mumkin (ko'p qatlamli — dashboard, marketing, admin — har biri o'z karkasi); (2) layout navigatsiyada saqlanadi/dashboard ichida sahifalar almashganda (settings analytics), DashboardLayout (sidebar) qayta render bo'lmaydi (faqat kontent o'zgaradi — performance, va sidebar state saqlanadi). Bu — murakkab ilova strukturasini (ko'p bo'limli dashboard) tabiiy va samarali qiladi.

2.4. Route groups — (group)

text
  ROUTE GROUP — fayllarni guruhlash, lekin URL'ni O'ZGARTIRMASDAN (qavs () bilan):

  app/
  ├── (marketing)/             qavs () — URL'da KO'RINMAYDI (faqat tashkilot)
  │   ├── layout.tsx          marketing layout (faqat shu guruh)
  │   ├── page.tsx            /                (NOT /marketing — qavs URL'da yo'q!)
  │   └── about/page.tsx      /about            (NOT /marketing/about)
  └── (shop)/
      ├── layout.tsx          shop layout (boshqa layout)
      ├── products/page.tsx   /products
      └── cart/page.tsx       /cart

  NEGA ROUTE GROUP:
   Turli LAYOUT'lar (marketing sahifalar bir layout, shop boshqa — URL'siz)
   Fayllarni mantiqiy guruhlash (URL'ni o'zgartirmasdan)

  ┌────────────────────────────────────────────────────────────┐
  │ (group): papka URL'da YO'Q (faqat tashkilot/layout)         │
  │  /about (NOT /marketing/about) — guruhlash URL'ni o'zgartirmaydi│
  └────────────────────────────────────────────────────────────┘

   (group) — qavs ichidagi papka URL'ga KIRMAYDI (faqat tashkilot + layout)
   Turli bo'limga turli layout berish uchun (marketing/shop/auth — har biri o'z layout)

Route groups — App Router'ning nozik, lekin foydali imkoniyati. Route group — papkani qavs () bilan o'rab, fayllarni guruhlash, lekin URL'ni o'zgartirmaslik. Misol: app/(marketing)/about/page.tsx URL /about (NOT /marketing/about(marketing) URL'da ko'rinmaydi, faqat tashkilot). Nega route group kerak: (1) turli layout'lar — masalan marketing sahifalari (bosh, about) bitta layout (oddiy navbar), shop sahifalari (products, cart) boshqa layout (savat ikonkasi bilan) — (marketing)/layout.tsx va (shop)/layout.tsx — lekin URL'lar bir xil darajada (/about, /products — guruh nomi URL'da yo'q); (2) fayllarni mantiqiy guruhlash (URL'ni o'zgartirmasdan — toza tashkilot). Ikki nuqta: (1) (group) — qavs ichidagi papka URL'ga kirmaydi (faqat tashkilot va layout uchun); (2) bu turli bo'limga (marketing/shop/auth — har biri o'z layout va navbar'iga ega, lekin URL'lar bir darajada) turli layout berishning toza usuli. Masalan (auth)/login, (auth)/register — login/register oddiy markazlashgan layout (sidebar yo'q), qolgan sahifalar to'liq layout — URL /login, /register (auth so'zi yo'q). Bu — fayl tashkiloti va layoutni URL'dan ajratish imkonini beradi (moslashuvchanlik).

2.5. Maxsus fayllar — loading, error, not-found

text
  MAXSUS FAYLLAR (App Router konvensiyasi — har biri aniq vazifa):

  page.tsx      sahifa (route)
  layout.tsx    o'rovchi layout 2.3-bob
  loading.tsx   yuklanish UI (Suspense AVTOMATIK — 13.1: Misol 7)
  error.tsx     xato UI (error boundary AVTOMATIK — "use client" majburiy)
  not-found.tsx 404 sahifa
  template.tsx  layout kabi, lekin HAR navigatsiyada qayta render (kam — 2.10)

  HAR PAPKADA bo'lishi mumkin (segment darajasida):
  app/dashboard/loading.tsx  faqat /dashboard yuklanishda
  app/dashboard/error.tsx    faqat /dashboard xatosida (boshqa bo'limga ta'sir yo'q)

  ┌────────────────────────────────────────────────────────────┐
  │ loading.tsx: Suspense | error.tsx: error boundary 11.12-bob   │
  │ not-found.tsx: 404 | — har papkada (segment darajasida)     │
  └────────────────────────────────────────────────────────────┘

   Maxsus fayl nomlari — Next.js konvensiyasi (loading/error/not-found avtomatik ishlaydi)
   Har papkada bo'lishi mumkin (granular — faqat o'sha bo'lim uchun — 11.12: 2.4 kabi)

Maxsus fayllar — App Router'ning konvensiya-asosli imkoniyatlari (11.8 Suspense va 11.12 error boundary'ni avtomatik qiladi). Asosiy maxsus fayllar (har biri aniq vazifaga ega): page.tsx (sahifa), layout.tsx (o'rovchi — 2.3), loading.tsx (yuklanish UI — Next.js avtomatik Suspense o'raydi — 13.1: Misol 7), error.tsx (xato UI — avtomatik error boundary; "use client" majburiy — chunki error boundary client'da ishlaydi — 11.12), not-found.tsx (404 sahifa), template.tsx (layout kabi, lekin har navigatsiyada qayta render — kam ishlatiladi — 2.10). Eng muhim — bular har papkada (segment darajasida) bo'lishi mumkin: app/dashboard/loading.tsx — faqat /dashboard yuklanishda; app/dashboard/error.tsx — faqat /dashboard xatosida (boshqa bo'limga ta'sir qilmaydi — granular — 11.12: 2.4). Ikki nuqta: (1) maxsus fayl nomlari — Next.js konvensiyasi (siz loading.tsx/error.tsx yaratasangiz, Next.js avtomatik Suspense/error boundary'ni qo'shadi — qo'lda o'rash kerak emas); (2) har papkada bo'lishi mumkin (granular izolyatsiya — bir bo'lim xatosi butun ilovani buzmaydi — 11.12: 2.4). Bu — robust, foydalanuvchiga g'amxo'r UI'ning avtomatik infratuzilmasi.

text
  IKKI NAVIGATSIYA USULI:

  1. <Link> — DEKLARATIV (foydalanuvchi bosadigan havola — 13.1: Misol 4):
  import Link from "next/link";
  <Link href="/products">Mahsulotlar</Link>              // prefetch avtomatik

  2. useRouter — DASTURIY (kod orqali — Client Component'da — "use client"):
  "use client";
  import { useRouter } from "next/navigation";    //  next/navigation (next/router EMAS — eski)
  const router = useRouter();
  router.push("/dashboard");        // o'sha sahifaga
  router.replace("/login");         // tarixni almashtir (orqaga qaytmasin)
  router.back();                    // orqaga
  router.refresh();                 // joriy sahifani server'dan qayta yukla

  SERVER'DA (Server Component/Action) — redirect:
  import { redirect, permanentRedirect } from "next/navigation";
  redirect("/login");               // server'da yo'naltirish (307/302 — vaqtinchalik)
  permanentRedirect("/new-url");    // doimiy yo'naltirish (308/301 — SEO, ko'chirilgan sahifa)

   <Link> — bosiladigan navigatsiya; useRouter — kod (hodisa/shart) — client'da
   redirect — server'da (Server Component/Action — 13.5); next/navigation'dan (yangi)

Navigatsiya — Link va useRouter — Next.js'da sahifalar orasida o'tishning uch usuli (React Router'ning — 11.9 — Next.js versiyalari). (1) <Link> — deklarativ (foydalanuvchi bosadigan havola — 13.1: Misol 4): <Link href="/products"> — client-side navigatsiya + avtomatik prefetch. (2) useRouter — dasturiy (kod orqali — Client Component'da, "use client" kerak): const router = useRouter() (next/navigation'dan — diqqat: next/router — eski Pages Router'niki — App Router'da next/navigation), keyin router.push("/dashboard") (o'sha sahifaga), router.replace("/login") (tarixni almashtirib — orqaga qaytmasin — 11.9: 2.9), router.back() (orqaga), router.refresh() (joriy sahifani server'dan qayta yukla — ma'lumot yangilangan bo'lsa). (3) redirectserver'da (Server Component yoki Server Action — 13.5): redirect("/login") (next/navigation'dan — server'da yo'naltirish, masalan auth tekshiruvida — vaqtinchalik, 307/302). Doimiy ko'chirish uchun esa permanentRedirect("/new-url") (308/301 — sahifa butunlay ko'chirilganda, SEO'ga to'g'ri signal). Ikki nuqta: (1) <Link> — bosiladigan navigatsiya; useRouter — kod (hodisa/shart natijasida — login'dan keyin) — client'da; redirect — server'da; (2) next/navigation (App Router) — next/router (Pages Router — eski) emas (bu keng xato). Bu uch usul — interaktiv oqimlar (login, forma submit, shartli yo'naltirish)ni qoplaydi.

2.7. usePathname va useSearchParams

text
  JORIY URL HAQIDA MA'LUMOT (Client Component'da — "use client"):

  usePathname — joriy YO'L (path):
  "use client";
  import { usePathname } from "next/navigation";
  const pathname = usePathname();      // "/products" (active link uchun)

  useSearchParams — query string (?filter=...):
  import { useSearchParams } from "next/navigation";
  const searchParams = useSearchParams();
  const category = searchParams.get("category");   // ?category=phone  "phone"

  ACTIVE LINK (joriy sahifani ajratish — navbar):
  const pathname = usePathname();
  <Link href="/products" className={pathname === "/products" ? "active" : ""}>...</Link>

  ┌────────────────────────────────────────────────────────────┐
  │ usePathname: joriy yo'l (/products) | useSearchParams: query │
  │ (Client Component — "use client"; React Router'ning o'xshashi)│
  └────────────────────────────────────────────────────────────┘

   usePathname/useSearchParams — Client Component'da (joriy URL — active link, filtr)
   Server Component — params/searchParams PROPS orqali (hook emas — 13.5)

usePathname va useSearchParams — joriy URL haqida ma'lumot olish (Client Component'da). usePathname — joriy yo'lni qaytaradi (const pathname = usePathname() "/products") — odatda active link uchun (navbar'da joriy sahifani ajratish — 11.9: 2.5 NavLink'ning Next.js usuli). useSearchParams — query string'ni o'qish (const searchParams = useSearchParams(); searchParams.get("category") ?category=phone "phone") — filtr, sahifalash holati uchun (11.9: 2.10 React Router'ning useSearchParamsiga o'xshaydi). Active link misol: usePathname() bilan joriy yo'lni olib, <Link className={pathname === "/products" ? "active" : ""}> (joriy sahifa havolasini ajratish). Ikki muhim nuqta: (1) usePathname/useSearchParamsClient Component'da ("use client" — bular hook, brauzerda ishlaydi); (2) Server Component'da esa params va searchParams props orqali olinadi (hook emas — sahifaga props sifatida beriladi — 13.5): export default function Page({ searchParams }) {...}. Bu farqni tushunish muhim — server'da props, client'da hook. Active link va filtr — bu hooklarning asosiy ishlatilishi.

2.8. generateStaticParams (dinamik SSG — 13.4 ko'prik)

text
  MUAMMO: dinamik sahifa ([id]) — qaysi id'lar BUILD paytida statik (SSG — 13.4) generatsiya?

  generateStaticParams — dinamik yo'llar uchun statik params (oldindan generatsiya):
  // app/products/[id]/page.tsx
  export async function generateStaticParams() {
    const products = await fetch("/api/products").then((r) => r.json());
    return products.map((p) => ({ id: p.id }));   //  har id uchun statik sahifa (build'da)
  }
  //  build paytida /products/1, /products/2, ... STATIK HTML generatsiya (SSG — tez)

  NEGA:
   Dinamik yo'l ([id]) + statik tezlik (build'da oldindan — SSG — 13.4)
   Blog post, mahsulot — ma'lum, o'zgarmaydigan  statik (eng tez)

  ┌────────────────────────────────────────────────────────────┐
  │ generateStaticParams: [id] yo'llar uchun statik sahifalar   │
  │ (build'da /products/1, /products/2... — SSG tezlik — 13.4)  │
  └────────────────────────────────────────────────────────────┘

   generateStaticParams — dinamik [id] yo'llarni build'da statik qiladi (SSG — 13.4)
   Blog/mahsulot (ma'lum, o'zgarmas)  statik (tez); 13.4'da rendering chuqur

generateStaticParams — dinamik yo'llarni statik (SSG) qilishning usuli (13.4 rendering bilan ko'prik). Muammo: dinamik sahifa ([id]) — Next.js qanday qilib build paytida statik HTML generatsiya qiladi (SSG — eng tez — 13.4)? Qaysi idlar uchun? Javob — generateStaticParams: export async function generateStaticParams() { const products = await fetch(...); return products.map((p) => ({ id: p.id })) } — bu funksiya build paytida ishlaydi va qaysi idlar uchun statik sahifa generatsiya qilishni aytadi (har mahsulot id'si uchun bittadan). Natijada build paytida /products/1, /products/2, ... — statik HTML generatsiya qilinadi (SSG — 13.4 — fayl sifatida, eng tez). Nega: dinamik yo'l ([id]) qulayligi + statik tezlik (build'da oldindan) — masalan blog post yoki mahsulot sahifalari (ma'lum, o'zgarmaydigan kontent) statik bo'lsa, eng tez ochiladi. Ikki nuqta: (1) generateStaticParams — dinamik [id] yo'llarni build paytida statik qiladi (SSG — 13.4); (2) blog, docs, mahsulot (ma'lum va kam o'zgaradigan) uchun statik ideal (tez, CDN'dan). Bu — 13.4'da rendering strategiyalari bilan chuqur ochiladi; hozircha shuni bilib qo'ying: dinamik yo'l ham statik bo'lishi mumkin (generateStaticParams orqali).

2.9. Parallel va intercepting routes (ilg'or — qisqa)

text
  ILG'OR ROUTING NAQSHLARI (kam, lekin kuchli — qisqa tanishtirish):

  PARALLEL ROUTES (@slot) — bir sahifada BIR NECHA mustaqil bo'lak:
  app/dashboard/
  ├── @team/page.tsx          @team slot
  ├── @analytics/page.tsx     @analytics slot
  └── layout.tsx              ikkalasini oladi: { team, analytics, children }
  //  dashboard'da team va analytics MUSTAQIL (har biri o'z loading/error) — murakkab dashboard

  INTERCEPTING ROUTES (.) — yo'lni "ushlab", boshqacha ko'rsatish:
  // masalan: rasm galereyasida rasmga bossangiz — MODAL'da ochiladi (URL o'zgaradi,
  // lekin to'liq sahifa emas — modal); to'g'ridan URL'da esa — to'liq sahifa
  app/feed/(..)photo/[id]/page.tsx    /photo/5 ni feed'da MODAL qilib ushlaydi

  ┌────────────────────────────────────────────────────────────┐
  │ Parallel (@slot): bir sahifada ko'p mustaqil bo'lak          │
  │ Intercepting (.): yo'lni ushlab modal (Instagram rasm kabi) │
  └────────────────────────────────────────────────────────────┘

   Parallel/intercepting — ilg'or (murakkab dashboard, modal-routing); kam, lekin kuchli
   Boshlang'ich loyihada kam kerak; lekin Instagram-uslubdagi modal — intercepting

Parallel va intercepting routes — App Router'ning ilg'or routing naqshlari (kam ishlatiladi, lekin kuchli — qisqa tanishtirish). Parallel routes (@slot) — bir sahifada bir necha mustaqil bo'lakni ko'rsatish: app/dashboard/@team/page.tsx va @analytics/page.tsxlayout.tsx ikkalasini alohida props sifatida oladi ({ team, analytics, children }), va ular mustaqil render bo'ladi (har biri o'z loading/error'iga ega) — murakkab dashboard uchun (masalan team statistikasi va analytics bir vaqtda, mustaqil yuklanadi). Intercepting routes ((.), (..)) — yo'lni "ushlab", uni boshqacha ko'rsatish: klassik misol — Instagram-uslubdagi rasm galereyasi: feed'da rasmga bossangiz, rasm modalda ochiladi (URL o'zgaradi /photo/5, lekin to'liq sahifa emas — modal feed ustida), lekin o'sha URL'ni to'g'ridan ochsangiz (yoki yangilasangiz) — to'liq sahifa. Ikki nuqta: (1) parallel (@slot) — bir sahifada ko'p mustaqil bo'lak (murakkab dashboard); intercepting ((.)) — yo'lni ushlab modal qilish (Instagram rasm, "quick view"); (2) bular ilg'or (boshlang'ich loyihada kam kerak), lekin murakkab UX (modal-routing, mustaqil panellar) uchun juda kuchli. Hozircha shuni bilib qo'ying: bunday narsalar mumkin (kerak bo'lganda o'rganasiz); ko'p ilova bularsiz ham ishlaydi. Bu — App Router'ning chuqurligini ko'rsatadi (React Router bunday narsani oson qila olmas edi).

2.10. Template vs layout va routing best practices

text
  TEMPLATE vs LAYOUT (nozik farq):
  layout.tsx    navigatsiyada SAQLANADI (state qoladi, qayta render yo'q — 2.3)
  template.tsx  HAR navigatsiyada YANGI nusxa (state reset, qayta render)
   template kam (masalan har sahifada kirish animatsiyasi, yoki useEffect har o'tishda)

  ROUTING BEST PRACTICES:
   page.tsx — faqat sahifa (boshqa komponentlar — alohida fayl/papka)
   Komponentlarni _components/ yoki components/da (route emas — 2.1)
   Nested layout — umumiy karkas (dashboard sidebar — 2.3)
   Route group — turli layout (URL'siz — 2.4)
   loading/error har bo'limda (granular — 2.5)
   Server Component default; "use client" faqat interaktiv (13.3)

   Layout — saqlanadi (afzal); template — har navigatsiyada yangi (kam — maxsus holat)
   page.tsx toza (faqat sahifa); komponentlar alohida; layout umumiy karkas

Template vs layout va best practices — routing'ni to'g'ri tashkil qilish. Template vs layout (nozik farq): layout.tsx — navigatsiyada saqlanadi (state qoladi, qayta render bo'lmaydi — 2.3 — sidebar misol); template.tsx — har navigatsiyada yangi nusxa (state reset, qayta render bo'ladi). template kam ishlatiladi — faqat har sahifada yangi boshlanishi kerak bo'lganda (masalan har sahifaga kirish animatsiyasi, yoki har o'tishda useEffect ishlashi kerak). Routing best practices: (1) page.tsx — faqat sahifa (boshqa komponentlarni alohida fayl/papkada); (2) komponentlarni _components/ (private — 2.1) yoki components/da saqlash (route emas); (3) nested layout — umumiy karkas (dashboard sidebar — 2.3); (4) route group — turli layout (URL'siz — 2.4); (5) loading/error har bo'limda (granular — 2.5); (6) Server Component default, "use client" faqat interaktiv 13.3-bob. Ikki nuqta: (1) layout — saqlanadi (afzal — performance, state); template — har navigatsiyada yangi (kam — maxsus holat — animatsiya); (2) page.tsx toza tut (faqat sahifa), komponentlar alohida, layout umumiy karkas. Bu — tartibli, kengaytiriladigan Next.js routing arxitekturasining asosi.

2.11. Root layout, template va not-found chuqurroq

text
  ROOT LAYOUT (app/layout.tsx) — MAJBURIY, <html> va <body>ni O'ZI beradi:

  // app/layout.tsx — butun ilovaning eng tashqi qobig'i (bitta, majburiy)
  export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
      <html lang="uz">          //  <html> va <body> FAQAT root layout'da (boshqa layout'da YO'Q)
        <body>{children}</body>
      </html>
    );
  }

  ┌────────────────────────────────────────────────────────────┐
  │ Root layout: MAJBURIY, <html>/<body> — faqat shu yerda      │
  │ Nested layout: <html>/<body> YO'Q (faqat root'da)           │
  └────────────────────────────────────────────────────────────┘

  NOT-FOUND (404) — ikki usul:
  1. app/not-found.tsx   butun ilova uchun 404 (yoki segment darajasida — dashboard/not-found.tsx)
  2. notFound() funksiya  kod ichida 404 chaqirish (next/navigation'dan):
     import { notFound } from "next/navigation";
     if (!product) notFound();      // ma'lumot topilmasa  not-found.tsx ko'rsatiladi

  TEMPLATE (template.tsx) — layout kabi, lekin HAR navigatsiyada yangi nusxa:
  // app/template.tsx — masalan har sahifaga kirish animatsiyasi
  export default function Template({ children }: { children: React.ReactNode }) {
    return <div className="fade-in">{children}</div>;   // har o'tishda YANGIDAN mount
  }

   Root layout — bitta, majburiy, <html>/<body> — faqat shu yerda
   notFound() — kod ichida 404 (topilmasa); not-found.tsx — 404 UI

Root layout, template va not-found (chuqurroq) — 2.3 va 2.5'ni to'ldiradi. Root layout (app/layout.tsx) — App Router'da majburiy (har ilovada bo'lishi shart), va u <html> va <body> teglarini o'zi beradi (<html lang="uz"><body>{children}</body></html>). Muhim: <html>/<body> faqat root layout'da bo'ladi — nested layout'lar (dashboard, marketing) ularni takrorlamaydi (faqat o'z <div>ini beradi). not-found (404) — ikki usul: (1) not-found.tsx fayl — butun ilova yoki segment (app/dashboard/not-found.tsx) uchun 404 UI; (2) notFound() funksiya (next/navigation'dan) — kod ichida chaqiriladi (if (!product) notFound() — masalan /products/999 topilmasa) va Next.js darrov eng yaqin not-found.tsxni ko'rsatadi (bu redirectga o'xshaydi — render to'xtaydi). template.tsxlayout.tsxka o'xshaydi (children oladi), lekin har navigatsiyada yangi nusxa mount qiladi (state reset) — masalan har sahifaga fade-in animatsiyasi yoki har o'tishda ishlashi kerak bo'lgan useEffect uchun. Ikki nuqta: (1) root layout — bitta, majburiy, <html>/<body> faqat shu yerda; (2) notFound() — kod ichidan 404 chaqirish (topilmagan ma'lumot uchun), not-found.tsx — o'sha 404'ning ko'rinishi.

2.12. Route Handlers (route.ts), default.tsx va metadata konvensiyalari

text
  ROUTE HANDLER (route.ts) — sahifa EMAS, API endpoint (06-bob API, 13.7 chuqur):
  // app/api/products/route.ts   GET/POST /api/products (JSON, HTML emas)
  export async function GET() {
    const products = await db.products.findMany();
    return Response.json(products);         //  page.tsx UI qaytaradi; route.ts Response
  }
   page.tsx va route.ts — BIR papkada birga BO'LMAYDI (biri UI, biri endpoint — to'qnashadi)

  DEFAULT.tsx — parallel route slot uchun "zaxira" UI (2.9 bilan bog'liq):
  // app/dashboard/@analytics/default.tsx  slot mos kelmasa shu ko'rsatiladi
  // (to'g'ridan URL ochilganda slot holati noma'lum  default.tsx zaxira)

  METADATA — SEO uchun (08/13.8-bobda chuqur — bu yerda faqat konvensiya):
  1. Fayl konvensiyasi:  app/favicon.ico, app/icon.png, app/opengraph-image.png (avtomatik)
  2. Export konvensiyasi: page.tsx/layout.tsx'da metadata export:
     export const metadata = { title: "Mahsulotlar", description: "..." };
     export async function generateMetadata({ params }) { ... }   // dinamik ([id] uchun)

   route.ts — API endpoint (Response), page.tsx — UI (JSX); bir papkada birga emas
   metadata — export (statik) yoki generateMetadata (dinamik) — 13.8'da chuqur

Route Handlers, default.tsx va metadataapp/ papkasidagi qolgan maxsus fayllar. route.ts (Route Handler) — bu sahifa emas, balki API endpoint: app/api/products/route.ts GET/POST /api/products (JSON qaytaradi, HTML emas). Ichida HTTP metodlari eksport qilinadi (export async function GET() { return Response.json(...) }). Muhim qoida: page.tsx va route.ts bir papkada birga bo'lmaydi — chunki biri UI (GET HTML), boshqasi endpoint (GET JSON) — to'qnashadi. Route Handler'lar 06-bob (API asoslari) va 13.7 (Next.js API)da chuqur ochiladi. default.tsx — parallel route 2.9-bob slot'lari uchun zaxira UI: to'g'ridan URL ochilganda (masalan /dashboardni yangilaganda) slot holati noma'lum bo'lishi mumkin — @analytics/default.tsx o'sha holda ko'rsatiladigan zaxira (fallback). Metadata — SEO uchun (08 va 13.8'da chuqur), bu yerda faqat routing konvensiyasi sifatida: (1) fayl konvensiyasiapp/favicon.ico, app/icon.png, app/opengraph-image.png (Next.js ularni avtomatik <head>ga qo'shadi); (2) export konvensiyasipage.tsx/layout.tsxda export const metadata = { title, description } (statik) yoki export async function generateMetadata({ params }) (dinamik — [id] sahifasi uchun, masalan mahsulot nomi title'ga). Ikki nuqta: (1) route.ts — API endpoint (Response qaytaradi), page.tsx — UI (JSX) — bir papkada birga emas; (2) metadata page.tsx/layout.tsxda export orqali (13.8'da chuqur).

2.13. Route segment config va streaming UI

text
  ROUTE SEGMENT CONFIG — page/layout/route'dan MAXSUS export bilan xatti-harakatni sozlash
  (13.4 rendering bilan chambarchas — bu yerda routing nuqtai-nazaridan):

  // app/products/[id]/page.tsx
  export const dynamic = "force-dynamic";   // har so'rovda server render (SSG emas)
  export const revalidate = 60;             // ISR — har 60 soniyada qayta generatsiya 13.4-bob
  export const dynamicParams = true;        // generateStaticParams'da yo'q id  server'da render
  export const fetchCache = "force-cache";  // fetch kesh xulqi

  STREAMING UI (loading.tsx bilan bog'liq — 2.5):
   loading.tsx = butun sahifa uchun Suspense fallback
   <Suspense> QO'LDA = sahifaning BIR QISMINI stream (sekin bo'lakni alohida yuklash):
    <Suspense fallback={<Spinner />}><SlowComponent /></Suspense>
   sahifaning tez qismi darrov, sekin bo'lak (SlowComponent) tayyor bo'lganda "oqib" keladi

   Segment config — export const dynamic/revalidate/... (sahifa xulqini sozlash — 13.4)
   Streaming — loading.tsx (butun) yoki <Suspense> (qisman) — sekin qism alohida oqadi

Route segment config va streaming UI — sahifa xatti-harakatini sozlash (13.4 rendering bilan ko'prik, bu yerda routing nuqtai-nazaridan qisqacha). Route segment configpage.tsx, layout.tsx yoki route.tsdan maxsus export const orqali segmentning xulqini boshqarish: export const dynamic = "force-dynamic" (har so'rovda server render — statik emas), export const revalidate = 60 (ISR — har 60 soniyada qayta generatsiya — 13.4), export const dynamicParams = true (generateStaticParams'da bo'lmagan id kelsa server'da render qilinadimi), export const fetchCache (fetch keshi xulqi). Bu eksportlar routing segmentiga biriktiriladi va 13.4'da chuqur ochiladi. Streaming UIloading.tsx 2.5-bob bilan bog'liq: loading.tsx — butun sahifa uchun Suspense fallback; qo'lda <Suspense> esa sahifaning bir qismini stream qiladi (<Suspense fallback={<Spinner />}><SlowComponent /></Suspense>) — sahifaning tez qismi darrov ko'rinadi, sekin bo'lak (masalan sekin API) tayyor bo'lganda "oqib" keladi (progressiv yuklash — foydalanuvchi bo'sh ekranni kutmaydi). Ikki nuqta: (1) segment config — export const dynamic/revalidate/... bilan sahifa xulqini sozlash 13.4-bob; (2) streaming — loading.tsx (butun sahifa) yoki <Suspense> (qisman — sekin bo'lak alohida oqadi).

2.14. App Router va Pages Router routing farqi

text
  APP ROUTER (app/) vs PAGES ROUTER (pages/) — routing jihatidan farq:

  ┌──────────────────┬───────────────────────┬───────────────────────┐
  │                  │ PAGES ROUTER (eski)    │ APP ROUTER (yangi)     │
  ├──────────────────┼───────────────────────┼───────────────────────┤
  │ Papka            │ pages/                 │ app/                   │
  │ Sahifa fayli     │ pages/about.tsx = /about│ app/about/page.tsx    │
  │ Dinamik          │ pages/[id].tsx         │ app/[id]/page.tsx      │
  │ Layout           │ _app.tsx (bitta global)│ layout.tsx (nested)    │
  │ Loading/Error    │ qo'lda                 │ loading.tsx/error.tsx  │
  │ Router hook      │ next/router (useRouter)│ next/navigation        │
  │ Data fetching    │ getServerSideProps/... │ async Server Component │
  │ Default render   │ har xil               │ Server Component        │
  └──────────────────┴───────────────────────┴───────────────────────┘

   Pages Router (eski) — pages/, next/router, getServerSideProps; App Router — app/, next/navigation
   Ikkalasi bir loyihada ishlashi mumkin (migratsiya), lekin yangi loyiha — App Router

App Router va Pages Router farqi — Next.js'da ikki routing tizimi bor va ularni chalkashtirmaslik muhim. Pages Router (eski, pages/ papka) — pages/about.tsx /about, dinamik pages/[id].tsx, bitta global layout (_app.tsx), navigatsiya next/router'dan (useRouter), ma'lumot olish getServerSideProps/getStaticProps. App Router (yangi, app/ papka — Next.js 13+) — app/about/page.tsx /about, nested layout (layout.tsx), loading.tsx/error.tsx avtomatik, navigatsiya next/navigation'dan, ma'lumot olish to'g'ridan async Server Component'da, default — Server Component. Ikki nuqta: (1) eng keng chalkashlik — next/router (Pages) va next/navigation (App) — App Router'da doim next/navigation; (2) ikkalasi bir loyihada birga ishlashi mumkin (bosqichma-bosqich migratsiya uchun), lekin yangi loyiha uchun App Router tavsiya etiladi (bu bob va butun 13-qism App Router'ga bag'ishlangan). Bu farqni bilish eski qo'llanmalar (Pages Router) bilan chalkashmaslik uchun zarur.


3. Sintaksis — tez ma'lumotnoma

text
SAHIFA 2.1-bob:      app/products/page.tsx  /products  (papka=yo'l, page.tsx=sahifa)
DINAMIK 2.2-bob:     [id]  /products/42 | [...slug]  /docs/a/b | [[...slug]]  optional
PARAMS 2.2-bob:      async function Page({ params }) { const { id } = await params }
LAYOUT 2.3-bob:      app/dashboard/layout.tsx — { children } (ichma-ich o'raydi)
ROUTE GROUP 2.4-bob: app/(marketing)/about/page.tsx  /about  (qavs URL'da yo'q)
MAXSUS 2.5-bob:      page | layout | loading | error("use client") | not-found
LINK 2.6-bob:        <Link href="/x"> | router.push() (useRouter — "use client") | redirect() (server)
PATH 2.7-bob:        usePathname() | useSearchParams() (Client) | params/searchParams props (Server)
STATIC 2.8-bob:      generateStaticParams() — [id] yo'llar uchun statik (SSG — 13.4)
ILG'OR 2.9-bob:      @slot (parallel) | (.) (intercepting — modal) | default.tsx (slot zaxira)
ROOT 2.11-bob:       app/layout.tsx — <html>/<body> (majburiy) | notFound() | template.tsx
ROUTE.TS 2.12-bob:   app/api/.../route.ts — GET/POST (API, Response — 06/13.7); page.tsx bilan birga emas
META 2.12-bob:       export const metadata = {...} | generateMetadata() (dinamik — 13.8)
CONFIG 2.13-bob:     export const dynamic/revalidate/dynamicParams (segment config — 13.4)
STREAM 2.13-bob:     loading.tsx (butun) | <Suspense> (qisman — sekin bo'lak oqadi)
FARQ 2.14-bob:       Pages Router (pages/, next/router) vs App Router (app/, next/navigation)

4. Batafsil kod namunalari

Har misol: Maqsad + izohli kod + "Bu kod nima qiladi".

Misol 1 — Dinamik mahsulot sahifasi ([id] + params — 2.2)

Maqsad: Bitta fayl bilan cheksiz mahsulot sahifasini yaratish — [id] dinamik segmenti va sahifa params'ni qanday olishini ko'rsatish. Bu e-commerce, blog, profil kabi har dinamik kontentning asosi.

tsx
// app/products/[id]/page.tsx  — [id] dinamik (har id uchun shu sahifa)
export default async function ProductPage({
  params,                              //  Next.js sahifaga params'ni props sifatida beradi
}: {
  params: Promise<{ id: string }>;     // Next.js 15: params Promise (async)
}) {
  const { id } = await params;         // URL'dan id'ni ol (/products/42  id = "42")

  // id bilan server'da to'g'ridan ma'lumot ol (Server Component — 13.1: Misol 5):
  const res = await fetch(`https://api.example.com/products/${id}`);
  const product = await res.json();

  return (
    <main>
      <h1>{product.name}</h1>           {/* o'sha id'dagi mahsulot */}
      <p>{product.price} so'm</p>
    </main>
  );
}

Bu kod nima qiladi: app/products/[id]/page.tsx faylida [id]dinamik segment: u /products/42, /products/100, /products/abc — har qanday qiymatga mos keladi (bitta fayl, cheksiz sahifa). Next.js sahifa komponentiga params prop'ini beradi — bu URL'dagi dinamik qiymatlarni o'z ichiga oladi. Next.js 15'da paramsPromise (shuning uchun await params) — bu so'rov ma'lumotlarining async tabiati uchun (13.1: 2.10). const { id } = await params bilan URL'dan idni ajratib olamiz (/products/42 id = "42"). Keyin shu id bilan server'da to'g'ridan ma'lumot olamiz (await fetch(.../products/${id}) — Server Component, useEffect/useState yo'q — 13.1: Misol 5), va o'sha mahsulotni ko'rsatamiz. Demak: [id] — dinamik yo'l, params — qiymat, va server'da ma'lumot = bitta fayl bilan cheksiz, tez, SEO'li mahsulot sahifalari. Bu — React Router'ning useParams (11.9: 2.6) bilan o'xshash, lekin server'da (props orqali, hook emas).

Misol 2 — Nested layout (dashboard sidebar — 2.3)

Maqsad: Faqat dashboard bo'limida ko'rinadigan sidebar yaratish (boshqa sahifalarda emas) — nested layout'ning ichma-ich o'rash xususiyatini ko'rsatish. Bu murakkab, ko'p-bo'limli ilova strukturasining asosidir.

tsx
// app/dashboard/layout.tsx — FAQAT /dashboard/* sahifalari uchun layout
export default function DashboardLayout({
  children,                            //  /dashboard ostidagi sahifalar bu yerga keladi
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="dashboard">
      {/* Sidebar — /dashboard ostidagi BARCHA sahifada ko'rinadi */}
      <aside className="sidebar">
        <nav>
          <a href="/dashboard">Bosh</a>
          <a href="/dashboard/settings">Sozlamalar</a>
          <a href="/dashboard/analytics">Analitika</a>
        </nav>
      </aside>
      {/* Asosiy kontent — URL'ga qarab o'zgaradi (settings yoki analytics) */}
      <main className="content">{children}</main>
    </div>
  );
}

Bu kod nima qiladi: app/dashboard/layout.tsx — bu nested layout (faqat dashboard/ papka ichidagi sahifalar uchun). U children prop'ini oladi — bu yerga /dashboard ostidagi har qanday sahifa (page.tsx, settings/page.tsx, analytics/page.tsx) avtomatik joylashtiriladi (React Router'ning Outlet'iga o'xshaydi — 11.9: 2.7, lekin Next.js fayl strukturasi orqali). Natijada: sidebar /dashboard ostidagi barcha sahifada ko'rinadi (bir marta yoziladi — layout'da), faqat {children} ichi URL'ga qarab o'zgaradi (/dashboard/settings SettingsPage, /dashboard/analytics AnalyticsPage). Eng muhim — bu layout faqat dashboard uchun (/about, /products sahifalarida yo'q — chunki ular dashboard/ papkasida emas). Va layout navigatsiyada saqlanadi (settings'dan analytics'ga o'tganda sidebar qayta render bo'lmaydi — faqat kontent — performance va state saqlash). Bu — root layout (umumiy navbar — har sahifa) + dashboard layout (sidebar — faqat dashboard) — ichma-ich layoutlarning kuchi.

Misol 3 — Route group (turli layout — 2.4)

Maqsad: Auth sahifalari (login/register)ga boshqa layout (markazlashgan, sidebar'siz) berish, lekin URL'ni /auth/login emas, /login qilish — route group'ning URL'ni o'zgartirmasdan guruhlash xususiyatini ko'rsatish.

tsx
// app/(auth)/layout.tsx — (auth) guruhi uchun layout (URL'da "auth" YO'Q)
export default function AuthLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="auth-layout">      {/* markazlashgan, sidebar'siz (login/register uchun) */}
      <div className="auth-card">{children}</div>
    </div>
  );
}

// app/(auth)/login/page.tsx  URL: /login (NOT /auth/login — qavs () URL'da yo'q!)
export default function LoginPage() {
  return <h1>Kirish</h1>;
}

// app/(auth)/register/page.tsx  URL: /register (NOT /auth/register)
export default function RegisterPage() {
  return <h1>Ro'yxatdan o'tish</h1>;
}

Bu kod nima qiladi: (auth)route group (qavs () bilan). Eng muhim: qavs ichidagi papka nomi URL'da ko'rinmaydiapp/(auth)/login/page.tsxning URL'i /login (NOT /auth/login). Nega bu foydali: (auth)/layout.tsx faqat login va register sahifalariga maxsus layout beradi (markazlashgan karta, sidebar va navbar yo'q — login sahifasiga mos), lekin URL'lar toza qoladi (/login, /register/auth/ prefiksi yo'q). Demak route group ikki narsani ajratadi: fayl tashkiloti (login/register birga, o'z layout'i bilan) va URL (toza, guruh nomi yo'q). Boshqa sahifalar (/dashboard, /products) o'z layout'iga ega (root + dashboard), auth sahifalari esa alohida ((auth) layout). Bu — bir ilovada turli layout'lar (marketing, shop, auth — har biri o'z karkasi) berishning toza usuli, URL strukturasini buzmasdan. Route group'siz, har layout uchun URL'da qo'shimcha segment bo'lardi (/auth/login — keraksiz).

Misol 4 — loading va error (maxsus fayllar — 2.5)

Maqsad: Yuklanish va xato holatlapini avtomatik boshqarish — loading.tsx va error.tsx maxsus fayllarini ko'rsatish. Bu 11.8 (Suspense) va 11.12 (error boundary)ni qo'lda o'ramasdan beradi.

tsx
// app/products/loading.tsx — /products yuklanayotganda AVTOMATIK ko'rinadi
export default function Loading() {
  // ProductsPage server'da ma'lumot olayot paytda (await fetch) bu ko'rsatiladi:
  return <div className="skeleton">Mahsulotlar yuklanmoqda...</div>;
}

// app/products/error.tsx — /products'da xato bo'lsa AVTOMATIK ko'rinadi
"use client";   //  error.tsx HAR DOIM Client Component (error boundary client'da — 11.12)

export default function Error({
  error,                        // xato obyekti
  reset,                        // qayta urinish funksiyasi
}: {
  error: Error;
  reset: () => void;
}) {
  return (
    <div className="error">
      <p>Xatolik: {error.message}</p>
      <button onClick={reset}>Qayta urinish</button>   {/* reset — qayta render */}
    </div>
  );
}

Bu kod nima qiladi: Ikki maxsus fayl, har biri avtomatik ishlaydi (11.8 va 11.12'ni qo'lda yozmasdan). loading.tsx/products sahifasi (Server Component) ma'lumot olayot paytda (await fetch — 13.1: Misol 5), Next.js avtomatik shu Loadingni ko'rsatadi (<Suspense fallback>ni o'zi o'raydi — siz qo'lda o'ramaysiz — 11.8). Ma'lumot tayyor bo'lganda — to'liq sahifa. error.tsx — agar /products sahifasida xato yuz bersa (masalan fetch muvaffaqiyatsiz), Next.js avtomatik shu Errorni ko'rsatadi (error boundary'ni o'zi o'raydi — 11.12). error.tsx har doim "use client" (Client Component) bo'lishi shart — chunki error boundary brauzerda ishlaydi va reset funksiyasi interaktiv. error prop — xato obyekti (xabarni ko'rsatish), reset — qayta urinish (komponentni qaytadan render qiladi). Natijada: foydalanuvchi hech qachon oq ekran yoki to'liq qulagan ilova ko'rmaydi — yuklanishda skeleton, xatoda "qayta urinish" tugmasi. Va bu faqat fayl yaratish bilan (qo'lda Suspense/error boundary — 11.8, 11.12 — kerak emas). Bu — fayl konvensiyasining kuchi.

Misol 5 — Dasturiy navigatsiya (useRouter — login oqimi — 2.6)

Maqsad: Login muvaffaqiyatli bo'lgandan keyin foydalanuvchini dashboard'ga kod orqali yo'naltirish — useRouterning dasturiy navigatsiyasini ko'rsatish (foydalanuvchi bosadigan havola emas, hodisa natijasida).

tsx
"use client";   //  useRouter — hook  Client Component
import { useRouter } from "next/navigation";   // App Router (next/router EMAS — 2.6)
import { useState } from "react";

export default function LoginForm() {
  const router = useRouter();              // dasturiy navigatsiya uchun
  const [error, setError] = useState("");

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    const res = await fetch("/api/login", { method: "POST", /* ... */ });
    if (res.ok) {
      router.push("/dashboard");           //  muvaffaqiyat  dashboard'ga (kod orqali)
      router.refresh();                    // server holatini yangila (auth tekshiruvi)
    } else {
      setError("Email yoki parol noto'g'ri");
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      {error && <p className="error">{error}</p>}
      <button type="submit">Kirish</button>
    </form>
  );
}

Bu kod nima qiladi: Bu — login formasi, va u dasturiy navigatsiyani ko'rsatadi (<Link> — foydalanuvchi bosadigan havola — emas, balki kod hodisa natijasida yo'naltiradi). "use client" — chunki useRouter hook va forma interaktiv (useState, onSubmit). useRouter()next/navigation'dan (App Router — diqqat: next/router Pages Router'niki, eski — 2.6). Forma yuborilganda: server'ga login so'rovi yuboriladi; agar muvaffaqiyatli (res.ok) — router.push("/dashboard") foydalanuvchini dashboard'ga kod bilan yo'naltiradi (foydalanuvchi bosmasdan — login muvaffaqiyatli bo'lgani uchun), va router.refresh() server holatini yangilaydi (auth o'zgardi — server'dagi protected sahifalar endi ruxsat beradi); agar muvaffaqiyatsiz — xato ko'rsatiladi. Demak useRouter — interaktiv oqimlar (login, forma submit, shartli yo'naltirish) uchun (11.9: 2.9 React Router'ning useNavigateiga o'xshaydi). router.push (o'tish), router.replace (orqaga qaytmasin), router.back (orqaga), router.refresh (server'dan yangila) — har biri o'z holati uchun.

Maqsad: Navbar'da joriy sahifani ajratib ko'rsatish (active link) — usePathname bilan joriy yo'lni olib, mos havolani belgilash. Bu har navbar'ning standart ehtiyoji.

tsx
"use client";   //  usePathname — hook  Client Component
import Link from "next/link";
import { usePathname } from "next/navigation";

export default function Navbar() {
  const pathname = usePathname();          // joriy yo'l ("/products" kabi)

  // Yordamchi — havola joriy sahifami (active class uchun):
  const linkClass = (href: string) =>
    pathname === href ? "nav-link active" : "nav-link";

  return (
    <nav>
      <Link href="/" className={linkClass("/")}>Bosh</Link>
      <Link href="/products" className={linkClass("/products")}>Mahsulotlar</Link>
      <Link href="/about" className={linkClass("/about")}>Biz haqimizda</Link>
    </nav>
  );
}

Bu kod nima qiladi: Bu — navbar, va u joriy sahifani ajratadi (foydalanuvchi qaerda ekanini ko'rsatadi — yaxshi UX). "use client" — chunki usePathname hook (brauzerda joriy URL'ni biladi). usePathname() — joriy yo'lni qaytaradi (/products sahifasida bo'lsak — "/products"). linkClass yordamchi funksiya — havola hrefini joriy pathname bilan solishtiradi: agar mos kelsa "active" class qo'shadi (CSS'da o'sha havolani ajratadi — masalan ko'k rang, ostida chiziq). Natijada: /products sahifasida bo'lganda, "Mahsulotlar" havolasi active class oladi (vizual ajralib turadi), qolganlari oddiy. Bu — React Router'ning <NavLink>iga (11.9: 2.5) o'xshaydi, lekin Next.js'da usePathname + <Link> bilan qo'lda (yoki shadcn/o'z komponentingda o'rab). Eslatma: bu komponent "use client" (hook ishlatadi), shuning uchun u client'da render bo'ladi — lekin u root layout'dagi server komponent ichida ishlatsa bo'ladi (server ichida client — 13.1: Misol 10). Navbar — interaktiv (active link), shuning uchun client mantiqli.

Misol 7 — Catch-all route ([...slug] — docs — 2.2)

Maqsad: Ko'p qatlamli yo'llarni (docs/wiki — /docs/guide/intro/setup) bitta fayl bilan boshqarish — [...slug] catch-all segmentini ko'rsatish. Bu hujjat (documentation) saytlari uchun ideal.

tsx
// app/docs/[...slug]/page.tsx — [...slug] BARCHA ostki yo'lni ushlaydi
export default async function DocsPage({
  params,
}: {
  params: Promise<{ slug: string[] }>;     //  slug — MASSIV (segmentlar)
}) {
  const { slug } = await params;
  // /docs/guide/intro  slug = ["guide", "intro"]
  // /docs/api/auth/login  slug = ["api", "auth", "login"]

  const path = slug.join("/");             // massivni yo'lga qayta birlashtir
  const doc = await fetch(`https://api.example.com/docs/${path}`).then((r) => r.json());

  return (
    <article>
      <h1>{doc.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: doc.content }} />   {/* docs HTML */}
    </article>
  );
}

Bu kod nima qiladi: [...slug]catch-all segment (uch nuqta ... bilan): u /docs ostidagi barcha yo'lni ushlaydi, qancha chuqur bo'lsa ham. Misol: /docs/guide/intro slug = ["guide", "intro"], /docs/api/auth/login slug = ["api", "auth", "login"]slug massiv bo'ladi (har segment — element). Oddiy [id] (Misol 1) faqat bitta segment oladi (/docs/guide — OK, lekin /docs/guide/intro — yo'q); [...slug] esa istalgan chuqurlikni (/docs/a/b/c/d). slug.join("/") — massivni qayta yo'lga birlashtiradi (["guide", "intro"] "guide/intro"), keyin shu yo'l bilan hujjatni olamiz. Natijada: bitta fayl ([...slug]/page.tsx) butun hujjat (docs) saytini boshqaradi — har sahifa (/docs/guide, /docs/guide/intro, /docs/api/auth/login) shu fayldan render bo'ladi. Bu docs, wiki, ko'p qatlamli kategoriya (/shop/electronics/phones/iphone) kabi noma'lum chuqurlikdagi yo'llar uchun ideal ([id] qila olmas edi — faqat bitta segment). [[...slug]] (optional) bo'lsa, /docs (segmentsiz) ham ishlardi.

Misol 8 — Server'da redirect (auth guard — 2.6, 13.5 ko'prik)

Maqsad: Himoyalangan sahifani server'da tekshirish — agar foydalanuvchi kirmagan bo'lsa, server'da login'ga yo'naltirish (redirect). Bu Client Component guard'dan 11.15-bob tezroq va xavfsizroq.

tsx
// app/dashboard/page.tsx — Server Component (himoyalangan)
import { redirect } from "next/navigation";   // server navigatsiya (2.6)
import { getServerSession } from "@/lib/auth";  // server'da sessiyani tekshir (13.9)

export default async function DashboardPage() {
  // Server'da auth tekshir (komponent render BO'LISHIDAN OLDIN):
  const session = await getServerSession();

  if (!session) {
    redirect("/login");                    //  kirmagan  server'da login'ga (render to'xtaydi)
  }

  // Bu yerga faqat AUTENTIFIKATSIYADAN o'tgan foydalanuvchi yetadi:
  return <h1>Dashboard — {session.user.name}</h1>;
}

Bu kod nima qiladi: Bu — himoyalangan dashboard sahifasi, va himoya server'da amalga oshiriladi (Client Component guard — 11.15: 2.6 — emas). DashboardPage Server Component (async) — server'da render bo'lishdan oldin auth tekshiriladi: await getServerSession() (server'da sessiya/token tekshir — 13.9). Agar sessiya yo'q (!session — foydalanuvchi kirmagan), redirect("/login") — server'da login'ga yo'naltiradi (next/navigation'dan — server navigatsiya — 2.6). Muhim: redirect chaqirilganda, komponent render to'xtaydi (returndan keyingi kod ishlamaydi) — foydalanuvchi dashboard'ni umuman ko'rmaydi (server uni render qilmaydi ham). Agar sessiya bor — komponent davom etadi va foydalanuvchi ma'lumoti bilan dashboard'ni ko'rsatadi. Nega server guard yaxshiroq (Client guard'dan — 11.15): (1) tezroq — server darrov yo'naltiradi (brauzer JavaScript yuklanishini kutmasdan); (2) xavfsizroq — himoyalangan kontent brauzerga umuman yuborilmaydi (Client guard'da kontent yuboriladi, keyin yashiriladi — texnik jihatdan ko'riladi). Bu — Next.js'ning server-first auth naqshi (13.9'da chuqur — NextAuth bilan).

Misol 9 — Komponentlarni tashkil qilish (route emas — 2.1, 2.10)

Maqsad: Sahifaga tegishli komponentlarni qaerda saqlash kerakligini ko'rsatish — page.tsxni toza tutish va komponentlarni route bo'lishdan saqlash. Bu loyiha tashkilotining muhim qismi.

tsx
// app/products/_components/ProductCard.tsx
//  _components — "_" bilan (private papka — route'ga AYLANMAYDI — 2.1)
export function ProductCard({ product }: { product: Product }) {
  return <div className="card">{product.name}</div>;
}

// app/products/page.tsx — sahifa (toza — faqat sahifa mantig'i)
import { ProductCard } from "./_components/ProductCard";   // local komponent

export default async function ProductsPage() {
  const products = await fetch("https://api.example.com/products").then((r) => r.json());
  return (
    <div className="grid">
      {products.map((p: Product) => (
        <ProductCard key={p.id} product={p} />   {/* tashkillangan komponent */}
      ))}
    </div>
  );
}

Bu kod nima qiladi: Bu — loyiha tashkilotining muhim naqshi: sahifaga tegishli, lekin route bo'lmasligi kerak bo'lgan komponentlarni qaerda saqlash. _componentsprivate papka (_ bilan boshlanadi) — Next.js uni route sifatida ko'rmaydi (_ bilan boshlangan papka URL'ga aylanmaydi — 2.1). Demak app/products/_components/ProductCard.tsx/products/_components/ProductCard URL'i emas (faqat tashkilot — komponent fayli). Bu nega muhim: agar oddiy components/ papka yaratsangiz, u ham route bo'lmaydi (faqat page.tsx route bo'ladi — 2.1), lekin _ prefiksi aniq "bu route emas" deb bildiradi (toza, niyat aniq). page.tsx esa toza qoladi — faqat sahifa mantig'i (ma'lumot olish, layout), komponentlar (ProductCard) alohida faylda. Natijada: sahifaga yaqin komponentlar (_components/da — sahifa bilan birga, lekin route emas), umumiy komponentlar esa app/components/ yoki src/components/da (butun ilova bo'ylab). Bu — page.tsxni toza, o'qish oson tutishning va komponentlarni mantiqiy tashkil qilishning usuli (2.10 best practice).

Misol 10 — generateStaticParams (blog SSG — 2.8)

Maqsad: Blog post'larni build paytida statik (SSG) qilish — generateStaticParams bilan barcha post'lar uchun oldindan HTML generatsiya. Bu eng tez yuklanadigan blog uchun.

tsx
// app/blog/[slug]/page.tsx

//  Build paytida ishlaydi — qaysi slug'lar uchun statik sahifa generatsiya (SSG — 13.4):
export async function generateStaticParams() {
  const posts = await fetch("https://api.example.com/posts").then((r) => r.json());
  // Har post uchun { slug } qaytar (build'da /blog/post-1, /blog/post-2... statik):
  return posts.map((post: { slug: string }) => ({ slug: post.slug }));
}

// Sahifa (har slug uchun — build'da statik HTML):
export default async function BlogPostPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await fetch(`https://api.example.com/posts/${slug}`).then((r) => r.json());
  return (
    <article>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  );
}

Bu kod nima qiladi: Bu — blog post sahifasi, va u build paytida statik (SSG — eng tez — 13.4) generatsiya qilinadi. generateStaticParams — maxsus, build paytida ishlaydigan funksiya: u barcha blog post'larni olib (fetch(.../posts)), har biri uchun { slug } qaytaradi. Next.js bu ro'yxatni ko'rib, build paytida har slug uchun statik HTML generatsiya qiladi: /blog/post-1.html, /blog/post-2.html, ... — oldindan tayyor fayllar. Natijada: foydalanuvchi /blog/my-first-postni ochsa, server darrov tayyor HTML faylni beradi (server'da render kutish yo'q, ma'lumot olish yo'q — fayl allaqachon tayyor — eng tez, CDN'dan ham beriladi). Bu SSR'dan (har so'rovda server render) tezroq, chunki ish build paytida bir marta qilingan. Nega blog uchun ideal: blog post'lar kam o'zgaradi (yozilgach — statik), shuning uchun har so'rovda qayta render qilishning ma'nosi yo'q — bir marta build'da generatsiya qilib, statik berish eng samarali. generateStaticParams'siz, bu sahifa SSR (har so'rovda server render) yoki on-demand bo'lardi. Bu — 13.4'da rendering strategiyalari bilan chuqur ochiladi; hozircha bil: dinamik yo'l ([slug]) + generateStaticParams = statik tezlik.


5. To'g'ri va noto'g'ri holatlar

1) Sahifa fayli

text
 app/products/index.tsx (Next.js page.tsx kutadi)
 app/products/page.tsx (aniq nom — 2.1)

2) Navigatsiya import

text
 import { useRouter } from "next/router"  (Pages Router — eski — 2.6)
 import { useRouter } from "next/navigation"  (App Router)

3) params

text
 const { id } = params  (Next.js 15 — params Promise — 2.2)
 const { id } = await params  (async)

4) error.tsx

text
 error.tsx Server Component (error boundary client'da — 2.5)
 "use client" (majburiy)

5) Route group

text
 app/auth/login  /auth/login (auth URL'da)
 app/(auth)/login  /login (qavs URL'siz — 2.4)

6) usePathname server'da

text
 Server Component'da usePathname (hook — client kerak)
 "use client" (Client Component'da — 2.7) yoki params props (Server)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — Sahifa 404 (mavjud bo'lsa ham)

Sababi: fayl page.tsx emas (masalan Page.tsx, index.tsx), yoki default export yo'q 2.1-bob. Yechimi: aniq page.tsx + export default.

Xato 2 — useRouter undefined / xato

Sababi: next/router (Pages Router) import qilindi 2.6-bob. Yechimi: next/navigation'dan import; "use client".

Xato 3 — params should be awaited

Sababi: Next.js 15 — params Promise, await qilinmagan 2.2-bob. Yechimi: const { id } = await params.

Xato 4 — error.tsx ishlamaydi

Sababi: "use client" yo'q 2.5-bob. Yechimi: error.tsx tepasiga "use client".

Xato 5 — Route group URL'da ko'rinadi

Sababi: qavs () yo'q (oddiy papka). Yechimi: (group) (qavs — URL'da yo'q — 2.4).

Xato 6 — Layout har navigatsiyada reset bo'ladi

Sababi: template.tsx ishlatilgan (layout o'rniga — 2.10). Yechimi: layout.tsx (saqlanadi); template faqat maxsus holat.

Xato 7 — Komponent fayli route bo'lib qoldi

Sababi: komponent page.tsx deb nomlangan yoki noto'g'ri joyda. Yechimi: komponentni _components/da (private — 2.1, Misol 9); faqat sahifa page.tsx.


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • React Router 11.9-bob: App Router — uning Next.js, fayl-asosli versiyasi (kuchliroq).
  • Server Components 13.3-bob: routing + ma'lumot — integratsiyalangan (Misol 1, 8).
  • Rendering 13.4-bob: generateStaticParams — dinamik yo'l SSG (Misol 10).
  • Auth 13.9-bob: server redirect (auth guard — Misol 8).
  • Loading/error (11.8, 11.12): loading.tsx/error.tsx — avtomatik (Misol 4).
  • Layout (11.9: 2.7): nested layouts — Outlet'ning fayl versiyasi (Misol 2).
  • Data fetching 13.5-bob: params/searchParams — sahifa ma'lumoti.
  • Metadata/SEO 13.8-bob: har sahifa/layout metadata.

8. Eng yaxshi amaliyotlar (best practices)

  • page.tsx faqat sahifa (komponentlar _components/da — 2.1, Misol 9).
  • next/navigation (App Router — next/router emas — 2.6).
  • await params (Next.js 15 — 2.2).
  • Nested layouts (umumiy karkas — dashboard sidebar — 2.3).
  • Route group turli layoutga (URL'siz — 2.4).
  • loading/error har bo'limda (granular — 2.5).
  • error.tsx "use client" (majburiy — 2.5).
  • generateStaticParams statik dinamik yo'lga (blog/docs — 2.8).
  • Server redirect auth guard'ga (Client guard'dan xavfsizroq — Misol 8).
  • Layout saqlanadi (template emas) 2.10-bob.

9. Amaliy loyiha: "Ko'p Sahifali Next.js Sayti (Routing)"

App Router routing'ni — dinamik, nested, group — real saytda mustahkamlash.

Maqsad

Blog + dashboard sayti qur: dinamik post sahifalari, nested dashboard layout, route group (auth), maxsus fayllar.

Talablar (requirements)

  1. Statik sahifalar: bosh, about, blog ro'yxati (Misol — 2.1).
  2. Dinamik: /blog/[slug] (post — params — Misol 1, 7).
  3. Catch-all: /docs/[...slug] (hujjat — Misol 7).
  4. Nested layout: /dashboard/* sidebar bilan (Misol 2).
  5. Route group: (auth)/login, (auth)/register /login, /register (Misol 3).
  6. Maxsus fayllar: loading.tsx + error.tsx (Misol 4).
  7. Navigatsiya: <Link> + active link (usePathname — Misol 6).
  8. Dasturiy: login router.push (Misol 5).
  9. Server guard: dashboard redirect (kirmagan login — Misol 8).
  10. generateStaticParams: blog post statik (Misol 10).

Maslahatlar (hint)

  • page.tsx — aniq nom (Xato 1).
  • next/navigation (next/router emas — Xato 2).
  • await params (Next.js 15 — Xato 3).
  • error.tsx — "use client" (Xato 4).
  • Route group — qavs () (Xato 5).
  • Komponentlar — _components/ (route emas — Misol 9).

"Tayyor" mezonlari (acceptance criteria)

  • Statik + dinamik sahifalar.
  • [slug] va [...slug] (params).
  • Nested dashboard layout (sidebar).
  • Route group (auth URL'siz).
  • loading/error (avtomatik).
  • Active link (usePathname).
  • Dasturiy navigatsiya (useRouter).
  • Server guard (redirect).
  • generateStaticParams (statik blog).

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda App Router routing'ni chuqur o'rgandik:

  • Fayl-routing (papka/page — 2.1); dinamik segmentlar ([id]/[...slug] — 2.2); nested layouts 2.3-bob; route groups ((group) — 2.4).
  • Maxsus fayllar (loading/error/not-found — 2.5); navigatsiya (<Link>/useRouter/redirect — 2.6); usePathname/useSearchParams 2.7-bob.
  • generateStaticParams (dinamik SSG — 2.8); parallel/intercepting (ilg'or — 2.9); template va best practices 2.10-bob.

Endi siz Next.js ilovasining skeletini — sahifalar, dinamik yo'llar, nested layout, navigatsiya, maxsus fayllar — fayl strukturasi orqali (kod emas) qura olasiz. Bu React Router'dan 11.9-bob ancha sodda va kuchli.

Keyingi bob — 13.3-bob: Server Components vs Client Components. Next.js App Router'ning eng muhim, eng inqilobiy tushunchasini chuqur o'rganamiz: Server Components (server'da render — default — tez, SEO, ma'lumot to'g'ridan, JavaScript brauzerga yuborilmaydi) vs Client Components ("use client" — interaktivlik, hook, hodisa). Qaysi qachon, ular qanday birga ishlaydi (kompozitsiya), ma'lumot va props qanday o'tadi, va eng keng tuzoqlar. Bu — Next.js'da to'g'ri, tez, samarali ilova qurishning kalitidir.


Foydalanilgan rasmiy/ishonchli manbalar

  • Next.js rasmiy hujjati (nextjs.org/docs/app) — "Routing Fundamentals", "Defining Routes", "Pages and Layouts", "Dynamic Routes", "Route Groups", "Loading UI and Streaming", "Error Handling", "Not Found"
  • nextjs.org — Linking and Navigating (<Link>, prefetch), Redirecting (redirect, permanentRedirect)
  • nextjs.org — next/navigation API: useRouter, usePathname, useSearchParams, redirect, notFound, permanentRedirect
  • nextjs.org — generateStaticParams, Route Segment Config (dynamic, revalidate, dynamicParams, fetchCache)
  • nextjs.org — Parallel Routes (@slot, default.js), Intercepting Routes ((.), (..), (...)), Project Organization (private folders _folder, colocation)
  • nextjs.org — Route Handlers (route.ts — GET/POST/...), Metadata Files va generateMetadata (SEO)
  • nextjs.org — File Conventions: page, layout, template, loading, error, not-found, route, default; Root Layout (majburiy <html>/<body>)
  • nextjs.org — App Router va Pages Router taqqoslash (Incremental Adoption / migratsiya qo'llanmasi)
  • React rasmiy hujjati (react.dev) — nested layouts, <Suspense> (loading.tsx va streaming asosi), Error Boundaries (error.tsx asosi)

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
13.2-bob: App Router va file-based routing — Wisar