Skip to content

Серверный await

Получение REST-данных на сервере до первого HTML.

Серверный await — базовая стратегия для данных, которые нужны до рендера страницы или серверного блока.

Когда использовать

  • Данные нужны для первого HTML.
  • Данные влияют на metadata.
  • По результату запроса нужно вызвать notFound() или redirect().
  • Компонент серверный и данные не зависят от состояния браузера.

Влияние на рендер

Серверный await сам по себе не означает SSR. В App Router страница может остаться static/ISR, если маршрут не использует dynamic API и запросы можно кешировать.

ISR — приоритет для общих данных. Если список или детальная страница могут обновляться по интервалу, сохраняйте кеширование и не добавляйте no-store, revalidate: 0 или force-dynamic без требования.

SSR/dynamic rendering нужен, когда данные зависят от текущего request: cookie, headers, searchParams, preview-режим или персональные данные пользователя.

Пример страницы списка

tsx
// src/app/(routes)/pets/page.tsx
import { petStoreApi } from 'infrastructure/pet-store-api'
import { PetsScreen } from 'screens/pets'

export default async function PetsPage() {
  const pets = await petStoreApi.pet.findPetsByStatus({
    status: 'available',
  })

  return <PetsScreen pets={pets} />
}

page.tsx получает данные первого рендера и передаёт их ниже. UI страницы остаётся в screens/, а не пишется прямо в app/.

Пример детальной страницы

tsx
// src/app/(routes)/pets/[id]/page.tsx
import { notFound } from 'next/navigation'
import { petStoreApi } from 'infrastructure/pet-store-api'
import { PetDetailScreen } from 'screens/pet-detail'

type PetPageProps = {
  params: Promise<{ id: string }>
}

export default async function PetPage({ params }: PetPageProps) {
  const { id } = await params
  const pet = await petStoreApi.pet.getPetById(Number(id)).catch(() => null)

  if (!pet) {
    notFound()
  }

  return <PetDetailScreen pet={pet} />
}

Обработка 404 зависит от API-клиента и класса ошибок. В примере показана идея: решение о notFound() принимается на уровне маршрута, а не внутри REST-клиента.

Что не делать

tsx
// Плохо — хуки нельзя вызывать в Server Component
const { data } = useGetPetList('available')

// Плохо — прямой fetch в обход клиента
const response = await fetch('https://petstore3.swagger.io/api/v3/pet/findByStatus')

Если данные нужны на сервере, вызывайте метод REST-клиента напрямую.

Когда выбрать другую стратегию