Веб-сайты

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

21.03.2026
← Все статьи

На протяжении многих лет Next.js остаётся одним из самых популярных фреймворков для проектов на React, однако появившийся в тринадцатой версии App Router радикально изменил всю архитектуру. Если вы раньше работали с Pages 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 — это Server Component (по умолчанию)
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. Вам больше не нужны отдельные функции загрузки данных, вы получаете данные прямо внутри компонента, и этот код никогда не доходит до браузера.

Файловая маршрутизация: page и layout

В App Router маршрут определяется каждой папкой, а файл page.tsx внутри папки представляет собой реальную страницу этого маршрута. Например, файл app/blog/page.tsx соответствует адресу /blog, а app/blog/[slug]/page.tsx — динамическому адресу вроде /blog/kakaya-to-statya. Кроме того, файл layout.tsx обеспечивает общую обёртку для всех страниц своей папки и всех вложенных, например панель навигации или подвал. Layout не перерендеривается при переходе между страницами, что очень полезно с точки зрения сохранения состояния и повышения производительности.

// app/blog/layout.tsx
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <section>
      <nav>Навигация блога</nav>
      {children}
    </section>
  )
}

Благодаря такой структуре общий каркас приложения и специфичная для страницы часть чётко разделяются. Layout-ы могут вкладываться друг в друга, то есть корневой layout оборачивает всё приложение, а затем каждый раздел может иметь собственный layout, что создаёт чрезвычайно гибкую иерархию интерфейса. Этот файловый подход продолжается и в управлении состояниями загрузки и ошибок.

App Router предлагает специальный файл loading.tsx, чтобы показать пользователю что-то во время загрузки данных. Вы просто добавляете файл с таким именем в папку, и Next.js автоматически отображает состояние загрузки, пока страница ожидает данные. Точно так же файл error.tsx срабатывает, когда во время рендеринга возникает ошибка, и он обязательно должен быть Client Component, поскольку перехватывает ошибку и предоставляет возможность повторной попытки.

// app/dashboard/loading.tsx
export default function Loading() {
  return <p>Данные загружаются...</p>
}

// app/dashboard/error.tsx
'use client'
export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <p>Произошла ошибка: {error.message}</p>
      <button onClick={() => reset()}>Повторить</button>
    </div>
  )
}

Этот механизм основан на концепциях Suspense и Error Boundary из React, но App Router автоматически оборачивает их через файловую систему. В результате вы получаете профессиональный опыт загрузки и обработки ошибок, не написав ни строчки шаблонного кода, а просто создав нужные файлы в правильных местах.

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">Отправить</button>
    </form>
  )
}

Такой подход значительно сглаживает границу между фронтендом и бэкендом. Теперь вам не нужно вручную писать REST или GraphQL эндпоинты, управлять вызовами fetch и снова и снова обрабатывать ошибки — вы просто пишете серверную функцию и связываете её с формой, что заметно ускоряет разработку.

Стратегии рендеринга: SSR, SSG и ISR

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

// SSG — по умолчанию, fetch кэшируется
await fetch('https://api.example.com/data')

// SSR — свежие данные на каждом запросе
await fetch(url, { cache: 'no-store' })

// ISR — обновление каждые 60 секунд
await fetch(url, { next: { revalidate: 60 } })

Как видите, в App Router стратегия рендеринга управляется через настройки вызова fetch, что даёт очень тонкий и точный контроль. Вы можете даже внутри одной страницы сделать одни данные статическими, а другие динамическими, что в Pages Router было практически невозможно. В целом App Router представляет собой мощную, гибкую и производительную основу для современных веб-приложений, и время, потраченное на его изучение, безусловно окупается. Если вы начинаете новый проект, выбор App Router станет наиболее правильным решением в долгосрочной перспективе.

Похожие статьи

🌾 Сайт сельского хозяйства и агробизнеса: каталог продукции и B2B-продажи ❤️ Сайт благотворительного фонда: прозрачный сбор и доверие донора 🎉 Сайт банкетного зала и места для свадьбы: организация события и онлайн-бронь 🚙 Сайт аренды автомобилей: каталог авто, калькулятор цен и онлайн-бронь
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский 🇬🇧 English