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. Это необходимо для корректной гидратации (hydration) страницы. Убедитесь, что вы не передаете в 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()

При использовании Инкрементальной статической регенерации (ISR), 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 route из getStaticProps (который сам получает данные из внешнего источника), можно написать серверный код напрямую в getStaticProps.

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

lib/load-posts.js
// Следующая функция используется совместно
// с getStaticProps и API routes
// из директории `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` route можно вызвать ту же
  // функцию напрямую в `getStaticProps`
  const posts = await loadPosts()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Режим предпросмотра (Preview Mode)

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