getStaticPaths

При экспорте функции getStaticPaths из страницы, использующей Динамические маршруты, Next.js будет статически предварительно рендерить все пути, указанные в getStaticPaths.

import type {
  InferGetStaticPropsType,
  GetStaticProps,
  GetStaticPaths,
} from 'next'

type Repo = {
  name: string
  stargazers_count: number
}

export const getStaticPaths = (async () => {
  return {
    paths: [
      {
        params: {
          name: 'next.js',
        },
      }, // См. раздел "paths" ниже
    ],
    fallback: true, // false или "blocking"
  }
}) satisfies GetStaticPaths

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 getStaticPaths() {
  return {
    paths: [
      {
        params: {
          name: 'next.js',
        },
      }, // См. раздел "paths" ниже
    ],
    fallback: true, // false или "blocking"
  }
}

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
}

Возвращаемые значения getStaticPaths

Функция getStaticPaths должна возвращать объект со следующими обязательными свойствами:

paths

Ключ paths определяет, какие пути будут предварительно отрендерены. Например, предположим, что у вас есть страница с Динамическими маршрутами под названием pages/posts/[id].js. Если вы экспортируете getStaticPaths из этой страницы и возвращаете следующее для paths:

return {
  paths: [
    { params: { id: '1' }},
    {
      params: { id: '2' },
      // при настройке i18n можно также вернуть локаль для пути
      locale: "en",
    },
  ],
  fallback: ...
}

Тогда Next.js статически сгенерирует /posts/1 и /posts/2 во время next build, используя компонент страницы в pages/posts/[id].js.

Значение каждого объекта params должно соответствовать параметрам, используемым в названии страницы:

  • Если название страницы pages/posts/[postId]/[commentId], то params должен содержать postId и commentId.
  • Если страница использует catch-all маршруты, например pages/[...slug], то params должен содержать slug (который является массивом). Если этот массив ['hello', 'world'], то Next.js статически сгенерирует страницу по адресу /hello/world.
  • Если страница использует опциональный catch-all маршрут, используйте null, [], undefined или false для рендеринга корневого маршрута. Например, если вы укажете slug: false для pages/[[...slug]], Next.js статически сгенерирует страницу /.

Строки в params чувствительны к регистру и желательно нормализовать их, чтобы пути генерировались корректно. Например, если для параметра возвращается WoRLD, он будет соответствовать только фактически посещенному пути WoRLD, а не world или World.

Помимо объекта params, можно вернуть поле locale при настройке i18n, которое определяет локаль для генерируемого пути.

fallback: false

Если fallback имеет значение false, то любые пути, не возвращенные getStaticPaths, приведут к 404 странице.

При запуске next build Next.js проверит, возвращает ли getStaticPaths fallback: false, и затем соберет только пути, возвращенные getStaticPaths. Этот вариант полезен, если у вас небольшое количество путей для создания или новые данные страниц добавляются нечасто. Если вам нужно добавить больше путей, а у вас установлен fallback: false, вам придется снова запустить next build, чтобы новые пути могли быть сгенерированы.

Следующий пример предварительно рендерит одну запись блога на странице под названием pages/posts/[id].js. Список записей блога будет получен из CMS и возвращен getStaticPaths. Затем для каждой страницы он получает данные записи из CMS с помощью getStaticProps.

pages/posts/[id].js
function Post({ post }) {
  // Рендеринг записи...
}

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

  // Получаем пути для предварительного рендеринга на основе записей
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // Мы предварительно рендерим только эти пути во время сборки.
  // { fallback: false } означает, что другие маршруты должны вернуть 404.
  return { paths, fallback: false }
}

// Эта функция также вызывается во время сборки
export async function getStaticProps({ params }) {
  // params содержит id записи.
  // Если маршрут выглядит как /posts/1, то params.id равен 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // Передаем данные записи на страницу через props
  return { props: { post } }
}

export default Post

fallback: true

Примеры

Если fallback имеет значение true, поведение getStaticProps изменяется следующим образом:

  • Пути, возвращенные из getStaticPaths, будут отрендерены в HTML во время сборки с помощью getStaticProps.
  • Пути, которые не были сгенерированы во время сборки, не приведут к 404 странице. Вместо этого Next.js будет отдавать "резервную" версию страницы при первом запросе такого пути. Веб-краулеры, такие как Google, не получат резервную версию, и путь будет вести себя как при fallback: 'blocking'.
  • При переходе на страницу с fallback: true через next/link или next/router (на стороне клиента) Next.js не будет отдавать резервную версию, и страница будет вести себя как fallback: 'blocking'.
  • В фоновом режиме Next.js статически сгенерирует запрошенный путь HTML и JSON. Это включает выполнение getStaticProps.
  • По завершении браузер получит JSON для сгенерированного пути. Это будет использовано для автоматического рендеринга страницы с требуемыми props. С точки зрения пользователя, страница переключится с резервной на полную версию.
  • В то же время Next.js добавляет этот путь в список предварительно отрендеренных страниц. Последующие запросы к тому же пути будут отдавать сгенерированную страницу, как и другие страницы, предварительно отрендеренные во время сборки.

Важно знать: fallback: true не поддерживается при использовании output: 'export'.

Когда полезен fallback: true?

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

Вместо этого вы можете статически сгенерировать небольшое подмножество страниц и использовать fallback: true для остальных. Когда кто-то запрашивает страницу, которая еще не сгенерирована, пользователь увидит страницу с индикатором загрузки или скелетоном компонента.

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

Это гарантирует, что пользователи всегда получают быстрый опыт, сохраняя при этом быструю сборку и преимущества статической генерации.

fallback: true не обновляет сгенерированные страницы, для этого см. Инкрементальную статическую регенерацию.

fallback: 'blocking'

Если fallback имеет значение 'blocking', новые пути, не возвращенные getStaticPaths, будут ждать генерации HTML, идентично SSR (отсюда и blocking), а затем кэшироваться для будущих запросов, так что это произойдет только один раз для каждого пути.

getStaticProps будет вести себя следующим образом:

  • Пути, возвращенные из getStaticPaths, будут отрендерены в HTML во время сборки с помощью getStaticProps.
  • Пути, которые не были сгенерированы во время сборки, не приведут к 404 странице. Вместо этого Next.js выполнит SSR при первом запросе и вернет сгенерированный HTML.
  • По завершении браузер получит HTML для сгенерированного пути. С точки зрения пользователя, переход будет от "браузер запрашивает страницу" к "полная страница загружена". Нет мигания состояния загрузки/резервной версии.
  • В то же время Next.js добавляет этот путь в список предварительно отрендеренных страниц. Последующие запросы к тому же пути будут отдавать сгенерированную страницу, как и другие страницы, предварительно отрендеренные во время сборки.

fallback: 'blocking' по умолчанию не обновляет сгенерированные страницы. Для обновления сгенерированных страниц используйте Инкрементальную статическую регенерацию вместе с fallback: 'blocking'.

Важно знать: fallback: 'blocking' не поддерживается при использовании output: 'export'.

Резервные страницы

В "резервной" версии страницы:

  • Props страницы будут пустыми.
  • Используя router, вы можете определить, рендерится ли резервная версия: router.isFallback будет true.

Следующий пример демонстрирует использование isFallback:

pages/posts/[id].js
import { useRouter } from 'next/router'

function Post({ post }) {
  const router = useRouter()

  // Если страница еще не сгенерирована, это будет отображено
  // изначально, пока getStaticProps() не завершит выполнение
  if (router.isFallback) {
    return <div>Загрузка...</div>
  }

  // Рендеринг записи...
}

// Эта функция вызывается во время сборки
export async function getStaticPaths() {
  return {
    // Только `/posts/1` и `/posts/2` генерируются во время сборки
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    // Включаем статическую генерацию дополнительных страниц
    // Например: `/posts/3`
    fallback: true,
  }
}

// Эта функция также вызывается во время сборки
export async function getStaticProps({ params }) {
  // params содержит id записи.
  // Если маршрут выглядит как /posts/1, то params.id равен 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()

  // Передаем данные записи на страницу через props
  return {
    props: { post },
    // Регенерировать запись не чаще одного раза в секунду
    // если поступает запрос
    revalidate: 1,
  }
}

export default Post

История версий

ВерсияИзменения
v13.4.0App Router теперь стабилен с упрощенным получением данных, включая generateStaticParams()
v12.2.0Инкрементальная статическая регенерация по запросу стабилизирована.
v12.1.0Добавлена Инкрементальная статическая регенерация по запросу (бета).
v9.5.0Стабилизирована Инкрементальная статическая регенерация
v9.3.0Добавлена getStaticPaths.