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
.
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
:
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.0 | App Router теперь стабилен с упрощенным получением данных, включая generateStaticParams() |
v12.2.0 | Инкрементальная статическая регенерация по запросу стабилизирована. |
v12.1.0 | Добавлена Инкрементальная статическая регенерация по запросу (бета). |
v9.5.0 | Стабилизирована Инкрементальная статическая регенерация |
v9.3.0 | Добавлена getStaticPaths . |