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',
},
}, // See the "paths" section below
],
fallback: true, // false or "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
}getStaticPaths 返回值
getStaticPaths 函数应返回一个包含以下必需属性的对象
paths
paths 键决定哪些路径将被预渲染。例如,假设你有一个使用动态路由的页面,名为pages/posts/[id].js。如果你从这个页面导出 getStaticPaths 并为 paths 返回以下内容:
return {
paths: [
{ params: { id: '1' }},
{
params: { id: '2' },
// with i18n configured the locale for the path can be returned as well
locale: "en",
},
],
fallback: ...
}那么,Next.js 将在 next build 期间使用 pages/posts/[id].js 中的页面组件静态生成 /posts/1 和 /posts/2。
每个 params 对象的值必须与页面名称中使用的参数匹配
- 如果页面名称是
pages/posts/[postId]/[commentId],那么params应该包含postId和commentId。 - 如果页面名称使用捕获所有路由,例如
pages/[...slug],那么params应该包含slug(这是一个数组)。如果这个数组是['hello', 'world'],那么 Next.js 将静态生成路径为/hello/world的页面。 - 如果页面使用可选捕获所有路由,则使用
null、[]、undefined或false来渲染最根部的路由。例如,如果为pages/[[...slug]]提供slug: false,Next.js 将静态生成页面/。
params 字符串是区分大小写的,理想情况下应进行规范化以确保路径正确生成。例如,如果参数返回 WoRLD,则只有当访问路径实际是 WoRLD 时才匹配,而不是 world 或 World。
除了 params 对象之外,当配置了国际化时,可以返回一个 locale 字段,该字段配置生成路径的语言环境。
fallback: false
如果 fallback 为 false,则任何未由 getStaticPaths 返回的路径都将导致一个 404 页面。
当运行 next build 时,Next.js 将检查 getStaticPaths 是否返回了 fallback: false,然后它将只构建 getStaticPaths 返回的路径。此选项适用于要创建的路径数量较少,或者不经常添加新页面数据的情况。如果你发现需要添加更多路径,并且设置了 fallback: false,则需要再次运行 next build 才能生成新路径。
以下示例为名为 pages/posts/[id].js 的每个页面预渲染一篇博客文章。博客文章列表将从 CMS 获取并由 getStaticPaths 返回。然后,对于每个页面,它使用 getStaticProps 从 CMS 获取文章数据。
function Post({ post }) {
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false }
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return { props: { post } }
}
export default Postfallback: true
示例
如果 fallback 为 true,则 getStaticProps 的行为将按以下方式更改:
- 从
getStaticPaths返回的路径将在构建时由getStaticProps渲染为HTML。 - 在构建时尚未生成的路径不会导致 404 页面。相反,Next.js 将在第一次请求此类路径时提供页面的“回退”版本。网络爬虫(例如 Google)不会获得回退页面,而是会像
fallback: 'blocking'那样处理该路径。 - 当通过
next/link或next/router(客户端)导航到带有fallback: true的页面时,Next.js 将不会提供回退,而是会像fallback: 'blocking'那样处理该页面。 - 在后台,Next.js 将静态生成请求路径的
HTML和JSON。这包括运行getStaticProps。 - 完成后,浏览器会收到生成路径的
JSON。这将用于使用所需的 props 自动渲染页面。从用户的角度来看,页面将从回退页面切换到完整页面。 - 同时,Next.js 将此路径添加到预渲染页面列表。后续对同一路径的请求将提供已生成的页面,就像在构建时预渲染的其他页面一样。
须知:使用
output: 'export'时,不支持fallback: true。
何时使用 fallback: true 很有用?
如果你的应用有大量依赖数据的静态页面(例如非常大的电子商务网站),那么 fallback: true 会非常有用。如果你想预渲染所有产品页面,构建时间会非常长。
相反,你可以静态生成一小部分页面,并将其余页面使用 fallback: true。当有人请求尚未生成的页面时,用户将看到带有加载指示器或骨架组件的页面。
不久之后,getStaticProps 完成,页面将使用请求的数据进行渲染。从现在开始,所有请求相同页面的用户都将获得静态预渲染的页面。
这确保了用户始终拥有快速的体验,同时保持了快速构建和静态生成的好处。
fallback: true 不会更新已生成的页面,为此请参阅增量式静态再生。
fallback: 'blocking'
如果 fallback 为 'blocking',则 getStaticPaths 未返回的新路径将等待 HTML 生成,与 SSR 完全相同(因此称为 blocking),然后缓存以供将来请求使用,这样每个路径只需生成一次。
getStaticProps 的行为如下:
- 从
getStaticPaths返回的路径将在构建时由getStaticProps渲染为HTML。 - 在构建时尚未生成的路径不会导致 404 页面。相反,Next.js 将在第一次请求时进行 SSR 并返回生成的
HTML。 - 完成后,浏览器会收到生成路径的
HTML。从用户的角度来看,它将从“浏览器正在请求页面”过渡到“完整页面已加载”。不会出现加载/回退状态的闪烁。 - 同时,Next.js 将此路径添加到预渲染页面列表。后续对同一路径的请求将提供已生成的页面,就像在构建时预渲染的其他页面一样。
默认情况下,fallback: 'blocking' 不会更新已生成的页面。要更新已生成的页面,请结合 fallback: 'blocking' 使用增量式静态再生。
须知:使用
output: 'export'时,不支持fallback: 'blocking'。
回退页面
在页面的“回退”版本中
- 页面的 props 将为空。
- 使用路由器,你可以检测是否正在渲染回退页面,
router.isFallback将为true。
以下示例展示了 isFallback 的用法
import { useRouter } from 'next/router'
function Post({ post }) {
const router = useRouter()
// If the page is not yet generated, this will be displayed
// initially until getStaticProps() finishes running
if (router.isFallback) {
return <div>Loading...</div>
}
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
return {
// Only `/posts/1` and `/posts/2` are generated at build time
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
// Enable statically generating additional pages
// For example: `/posts/3`
fallback: true,
}
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return {
props: { post },
// Re-generate the post at most once per second
// if a request comes in
revalidate: 1,
}
}
export default Post版本历史
| 版本 | 更改 |
|---|---|
v13.4.0 | App Router 现已稳定,并简化了数据获取,包括 generateStaticParams() |
v12.2.0 | 按需增量式静态再生 已稳定。 |
v12.1.0 | 添加了按需增量式静态再生(Beta)。 |
v9.5.0 | 稳定的增量式静态再生 |
v9.3.0 | 引入了 getStaticPaths。 |
这有帮助吗?