Веб-сайт

Next.js App Router: замонавий React фреймворк архитектураси

21.03.2026
← Барча мақолалар

Next.js кўп йиллар давомида React асосидаги лойиҳалар учун энг машҳур фреймворклардан бири бўлиб келган, аммо унинг 13-версиясидан бошлаб жорий этилган App Router бутун архитектурани тубдан ўзгартирди. Агар сиз илгари Pages Router билан ишлаган бўлсангиз, App Router бошида ғалати туюлиши мумкин, чунки у нафақат папкалар тузилишини, балки маълумотларни юклаш ва саҳифани рендер қилиш фалсафасини ҳам қайтадан кўриб чиқади. Ушбу мақолада биз App Router'нинг асосий ғояларини, эски ёндашувдан фарқини ва ҳар бир имкониятни реал код мисоллари орқали батафсил кўриб чиқамиз, шунда сиз ўз лойиҳангизда қайси ёндашувни танлашни аниқ тушунасиз.

Pages Router ва App Router ўртасидаги туб фарқ

Эски Pages Router'да ҳар бир файл pages папкасида жойлашган ва у тўғридан-тўғри браузерда ишлайдиган компонентга айланарди. Маълумотларни юклаш учун сиз getServerSideProps ёки getStaticProps каби махсус функцияларни экспорт қилишингиз керак эди, бу эса компонент мантиғи билан маълумот мантиғини сунъий равишда ажратиб қўярди. App Router эса app папкасига асосланади ва бу ерда компонентлар стандарт ҳолатда Server Components ҳисобланади, яъни улар фақат серверда ишлайди ва браузерга JavaScript юбормайди. Бу фарқ жуда муҳим, чунки у саҳифанинг юкланиш тезлигига, SEO кўрсаткичларига ва умумий фойдаланувчи тажрибасига бевосита таъсир қилади.

App Router'нинг яна бир кучли томони шундаки, у layout, loading ва error ҳолатларини файл тизими орқали табиий равишда бошқаришга имкон беради. Pages Router'да бундай ҳолатларни қўлда бошқариш керак эди, App Router эса махсус номланган файллар ёрдамида уларни автоматик равишда ушлаб олади. Қуйида биз ушбу механизмларнинг ҳар бирини алоҳида кўриб чиқамиз.

Server Components — стандарт ҳолатдаги янги ёндашув

App Router'да яратилган ҳар қандай компонент агар сиз аниқ белгиламасангиз, Server Component ҳисобланади. Бу дегани компонент серверда рендер қилинади, ундаги код браузерга умуман етиб бормайди, натижада илованинг JavaScript ҳажми сезиларли даражада камаяди. Server Components маълумотлар базасига тўғридан-тўғри мурожаат қила олади, махфий API калитлардан фойдаланиши мумкин ва оғир кутубхоналарни мижоз браузерига юкламасдан ишлатиши мумкин. Агар сизга интерактивлик, яъни useState, useEffect ёки ҳодисаларни эшитиш керак бўлса, файлнинг энг юқорисига 'use client' директивасини қўшасиз ва у Client Component'га айланади.

// app/products/page.tsx — bu Server Component (standart)
async function getProducts() {
  const res = await fetch('https://api.example.com/products')
  return res.json()
}

export default async function ProductsPage() {
  const products = await getProducts()
  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>{p.name}</li>
      ))}
    </ul>
  )
}

Юқоридаги мисолда компонентнинг ўзи async эканлигига эътибор беринг. Бу App Router'нинг энг ёқимли хусусиятларидан бири: Server Component тўғридан-тўғри асинхрон бўлиши ва await ишлатиши мумкин. Сизга энди алоҳида data fetching функциялари керак эмас, маълумотни тўғридан-тўғри компонент ичида юклайсиз ва бу код ҳеч қачон браузерга етиб бормайди.

Файл асосидаги маршрутлаш: page ва layout

App Router'да маршрут ҳар бир папка орқали аниқланади ва папка ичидаги page.tsx файли ўша маршрутнинг ҳақиқий саҳифасини ифодалайди. Масалан app/blog/page.tsx файли /blog манзилига, app/blog/[slug]/page.tsx эса динамик /blog/бирор-мақола манзилига мос келади. Бундан ташқари layout.tsx файли ўзининг папкасидаги ва ундан пастдаги барча саҳифалар учун умумий ўрамни таъминлайди, масалан навигация панели ёки футер. Layout саҳифалар алмашганда қайта рендер қилинмайди, бу эса ҳолатни сақлаб қолиш ва ишлаш унумдорлигини ошириш нуқтаи назаридан жуда фойдали.

// app/blog/layout.tsx
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      <nav>Blog navigatsiyasi</nav>
      {children}
    </section>
  )
}

Ушбу тузилма туфайли илованинг умумий каркаси ва саҳифага хос қисм аниқ ажратилади. Layoutlar бир-бирининг ичига жойлашиши мумкин, яъни илдиз layout бутун илована ўраб олади, ундан кейин ҳар бир бўлим ўз layoutiга эга бўлиши мумкин ва бу жуда мослашувчан иерархияни вужудга келтиради. Бу файл асосидаги ёндашув юкланиш ва хато ҳолатларини бошқаришда ҳам давом этади.

App Router маълумотлар юкланаётган пайтда фойдаланувчига нимадир кўрсатиш учун махсус loading.tsx файлини таклиф қилади. Сиз шунчаки папкага шу номдаги файл қўшасиз ва Next.js у ердаги саҳифа маълумот кутаётган пайтда автоматик равишда юкланиш ҳолатини кўрсатади. Худди шундай error.tsx файли рендер пайтида хато юз берганда ишга тушади ва у албатта Client Component бўлиши керак, чунки у хатони қайта уриниш имконияти билан ушлаб олади.

// app/dashboard/loading.tsx
export default function Loading() {
  return <p>Loading data...</p>
}

// app/dashboard/error.tsx
'use client'
export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <p>Xatolik yuz berdi: {error.message}</p>
      <button onClick={() => reset()}>Qayta urinish</button>
    </div>
  )
}

Бу механизм React'нинг Suspense ва Error Boundary концепцияларига асосланади, аммо App Router уларни файл тизими орқали автоматик ўраб беради. Натижада сиз boilerplate кодни ёзмасдан, фақат тегишли файлларни яратиш орқали профессионал юкланиш ва хато тажрибасини оласиз.

Server Actions — формалар ва мутациялар

Server Actions App Router'нинг энг инқилобий имкониятларидан бири бўлиб, у серверда ишлайдиган функцияларни тўғридан-тўғри компонент ичидан чақиришга имкон беради, алоҳида API эндпоинт яратмасдан. Сиз функциянинг юқорисига 'use server' директивасини қўясиз ва уни форма орқали ёки тугма босилишида ишга туширасиз. Бу маълумотларни сақлаш, янгилаш ёки ўчириш учун ажойиб, чунки барча мантиқ серверда қолади ва мижоз тарафига ортиқча код юборилмайди.

// app/contact/page.tsx
export default function ContactPage() {
  async function submit(formData: FormData) {
    'use server'
    const name = formData.get('name')
    await saveToDatabase({ name })
  }
  return (
    <form action={submit}>
      <input name="name" />
      <button type="submit">Yuborish</button>
    </form>
  )
}

Бу ёндашув frontend ва backend ўртасидаги чегарани анча силлиқлаштиради. Энди сиз REST ёки GraphQL эндпоинтларни қўлда ёзиш, fetch чақирувларини бошқариш ва хатоларни қайта-қайта ишлаш билан овора бўлмайсиз, балки шунчаки сервер функциясини ёзасиз ва уни форма билан боғлайсиз.

Рендер стратегиялари: SSR, SSG ва ISR

App Router учта асосий рендер стратегиясини қўллаб-қувватлайди ва уларни танлаш сизнинг маълумотларингиз қанчалик тез-тез ўзгаришига боғлиқ. Static Site Generation (SSG) саҳифани қуриш пайтида бир марта яратади ва у энг тез ишлайди, блог ёки ҳужжатлар учун идеал. Server-Side Rendering (SSR) эса ҳар бир сўровда саҳифани серверда қайтадан рендер қилади, бу доимо янги маълумот талаб қилинадиган ҳолатлар учун мос келади. Incremental Static Regeneration (ISR) иккаласининг ўртасини топади: саҳифа статик тарзда яратилади, аммо белгиланган вақт ўтгач фон режимида янгиланади.

// SSG — standart, fetch keshlanadi
await fetch('https://api.example.com/data')

// SSR — har so'rovda yangi
await fetch(url, { cache: 'no-store' })

// ISR — har 60 soniyada yangilanadi
await fetch(url, { next: { revalidate: 60 } })

Кўриб турганингиздек, App Router'да рендер стратегияси fetch чақирувининг созламалари орқали бошқарилади, бу жуда нозик ва аниқ назоратни беради. Сиз ҳатто бир саҳифанинг ичида баъзи маълумотларни статик, бошқаларини эса динамик қилиб олишингиз мумкин, бу эса илгари Pages Router'да деярли имконсиз эди. Умуман олганда App Router замонавий веб-иловалар учун кучли, мослашувчан ва унумдор асос бўлиб, уни ўрганишга сарфланган вақт албатта ўзини оқлайди. Агар сиз янги лойиҳа бошлаётган бўлсангиз, App Router'ни танлаш узоқ муддатда энг тўғри қарор бўлади.

Ўхшаш мақолалар

🌾 Қишлоқ хўжалиги ва агро сайти: маҳсулотлар каталоги ❤️ Хайрия фонди сайти: шаффоф ва ишонч 🎉 Тўйxона ва банкет зали сайти: бирон қилиш 🚙 Автомобил ижара сайти: каталог ва бирон
🌐 Тил
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский 🇬🇧 English