getStaticProps

Если вы экспортируете функцию getStaticProps (Статическая генерация сайтов) из страницы, Next.js предварительно отрендерит эту страницу во время сборки, используя пропсы, возвращённые getStaticProps.

import type { InferGetStaticPropsType, GetStaticProps } from 'next'

type Repo = {
  name: string
  stargazers_count: number
}

export const getStaticProps = (async (context) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}) satisfies GetStaticProps<{
  repo: Repo
}>

export default function Page({
  repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
  return repo.stargazers_count
}
export async function getStaticProps() {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}

export default function Page({ repo }) {
  return repo.stargazers_count
}

Обратите внимание, что независимо от типа рендеринга, любые props будут переданы в компонент страницы и могут быть просмотрены на стороне клиента в исходном HTML. Это необходимо для правильного гидратирования страницы. Убедитесь, что вы не передаёте в props никакой конфиденциальной информации, которая не должна быть доступна на клиенте.

Справочник по API getStaticProps охватывает все параметры и пропсы, которые можно использовать с getStaticProps.

Когда следует использовать getStaticProps?

Используйте getStaticProps, если:

  • Данные, необходимые для рендеринга страницы, доступны во время сборки до запроса пользователя
  • Данные поступают из headless CMS
  • Страница должна быть предварительно отрендерена (для SEO) и быть очень быстрой — getStaticProps генерирует файлы HTML и JSON, которые могут кэшироваться CDN для повышения производительности
  • Данные могут быть публично закэшированы (не специфичны для пользователя). Это условие можно обойти в определённых ситуациях, используя Middleware для перезаписи пути.

Когда выполняется getStaticProps

getStaticProps всегда выполняется на сервере и никогда на клиенте. Вы можете проверить, что код внутри getStaticProps удалён из клиентского бандла, с помощью этого инструмента.

  • getStaticProps всегда выполняется во время next build
  • getStaticProps выполняется в фоновом режиме при использовании fallback: true
  • getStaticProps вызывается перед первоначальным рендерингом при использовании fallback: blocking
  • getStaticProps выполняется в фоновом режиме при использовании revalidate
  • getStaticProps выполняется по запросу в фоновом режиме при использовании revalidate()

При использовании Инкрементальной статической регенерации getStaticProps будет выполняться в фоновом режиме, пока устаревшая страница перевалидируется, а свежая страница будет отправлена в браузер.

getStaticProps не имеет доступа к входящему запросу (например, параметрам запроса или HTTP-заголовкам), так как генерирует статический HTML. Если вам нужен доступ к запросу для вашей страницы, рассмотрите возможность использования Middleware вместе с getStaticProps.

Использование getStaticProps для получения данных из CMS

Следующий пример показывает, как можно получить список постов блога из CMS.

// posts будут заполнены во время сборки с помощью getStaticProps()
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

// Эта функция вызывается во время сборки на стороне сервера.
// Она не вызывается на стороне клиента, поэтому можно даже
// делать прямые запросы к базе данных.
export async function getStaticProps() {
  // Вызов внешнего API для получения постов.
  // Можно использовать любую библиотеку для получения данных
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Возвращая { props: { posts } }, компонент Blog
  // получит `posts` как проп во время сборки
  return {
    props: {
      posts,
    },
  }
}
// posts будут заполнены во время сборки с помощью getStaticProps()
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

// Эта функция вызывается во время сборки на стороне сервера.
// Она не вызывается на стороне клиента, поэтому можно даже
// делать прямые запросы к базе данных.
export async function getStaticProps() {
  // Вызов внешнего API для получения постов.
  // Можно использовать любую библиотеку для получения данных
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Возвращая { props: { posts } }, компонент Blog
  // получит `posts` как проп во время сборки
  return {
    props: {
      posts,
    },
  }
}

Справочник по API getStaticProps охватывает все параметры и пропсы, которые можно использовать с getStaticProps.

Написание серверного кода напрямую

Поскольку getStaticProps выполняется только на стороне сервера, он никогда не выполняется на стороне клиента. Он даже не включается в JS-бандл для браузера, поэтому можно писать прямые запросы к базе данных, не отправляя их в браузеры.

Это означает, что вместо получения данных через API-роут из getStaticProps (который сам получает данные из внешнего источника), можно написать серверный код напрямую в getStaticProps.

Рассмотрим следующий пример. API-роут используется для получения данных из CMS. Затем этот API-роут вызывается напрямую из getStaticProps. Это создаёт дополнительный вызов, снижая производительность. Вместо этого логику получения данных из CMS можно вынести в директорию lib/. Затем её можно использовать совместно с getStaticProps.

lib/load-posts.js
// Следующая функция используется совместно
// с getStaticProps и API-роутами
// из директории `lib/`
export async function loadPosts() {
  // Вызов внешнего API для получения постов
  const res = await fetch('https://.../posts/')
  const data = await res.json()

  return data
}
pages/blog.js
// pages/blog.js
import { loadPosts } from '../lib/load-posts'

// Эта функция выполняется только на стороне сервера
export async function getStaticProps() {
  // Вместо вызова вашего `/api` роута можно вызвать ту же
  // функцию напрямую в `getStaticProps`
  const posts = await loadPosts()

  // Возвращаемые props будут переданы в компонент страницы
  return { props: { posts } }
}

Альтернативно, если вы не используете API-роуты для получения данных, то API fetch() можно использовать напрямую в getStaticProps для получения данных.

Чтобы проверить, что Next.js удаляет из клиентского бандла, можно использовать инструмент next-code-elimination.

Статическая генерация HTML и JSON

Когда страница с getStaticProps предварительно рендерится во время сборки, помимо HTML-файла страницы, Next.js генерирует JSON-файл с результатом выполнения getStaticProps.

Этот JSON-файл используется при клиентской маршрутизации через next/link или next/router. При переходе на страницу, предварительно отрендеренную с помощью getStaticProps, Next.js получает этот JSON-файл (предварительно вычисленный во время сборки) и использует его как пропсы для компонента страницы. Это означает, что клиентские переходы между страницами не вызывают getStaticProps, так как используется только экспортированный JSON.

При использовании Инкрементальной статической регенерации getStaticProps будет выполняться в фоновом режиме для генерации JSON, необходимого для клиентской навигации. Вы можете увидеть это в виде нескольких запросов для одной и той же страницы, однако это ожидаемо и не влияет на производительность для конечного пользователя.

Где можно использовать getStaticProps

getStaticProps можно экспортировать только из страницы. Его нельзя экспортировать из нестраничных файлов, _app, _document или _error.

Одно из ограничений связано с тем, что React должен иметь все необходимые данные до рендеринга страницы.

Также необходимо экспортировать getStaticProps как отдельную функцию — он не будет работать, если добавить getStaticProps как свойство компонента страницы.

Полезно знать: если вы создали кастомное приложение, убедитесь, что передаёте pageProps в компонент страницы, как показано в документе, иначе пропсы будут пустыми.

Выполняется при каждом запросе в режиме разработки

В режиме разработки (next dev) getStaticProps будет вызываться при каждом запросе.

Режим предпросмотра

Вы можете временно обойти статическую генерацию и рендерить страницу во время запроса вместо времени сборки, используя Режим предпросмотра. Например, если вы используете headless CMS и хотите просмотреть черновики перед их публикацией.