跳到主要内容

getStaticPaths

如果页面具有动态路由并使用 getStaticProps,它需要定义要静态生成的路径列表。

当你从使用动态路由的页面导出一个名为 getStaticPaths(静态站点生成)的函数时,Next.js 将静态预渲染由 getStaticPaths 指定的所有路径。

pages/repo/[name].tsx
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
}

getStaticPaths API 参考涵盖了可以与 getStaticPaths 一起使用的所有参数和 props。

何时应该使用 getStaticPaths?

如果你要静态预渲染使用动态路由的页面,并且满足以下条件,则应使用 getStaticPaths

  • 数据来自无头 CMS
  • 数据来自数据库
  • 数据来自文件系统
  • 数据可以公开缓存(不是特定于用户的)
  • 页面必须预渲染(用于 SEO)并且要非常快 —— getStaticProps 生成 HTMLJSON 文件,两者都可以被 CDN 缓存以提升性能

getStaticPaths 何时运行

getStaticPaths 仅在生产环境的构建期间运行,不会在运行时调用。你可以使用这个工具验证 getStaticPaths 内编写的代码是否从客户端打包中移除。

getStaticProps 如何与 getStaticPaths 一起运行

  • getStaticPropsnext build 期间为构建期间返回的任何 paths 运行
  • 使用 fallback: true 时,getStaticProps 在后台运行
  • 使用 fallback: blocking 时,getStaticProps 在初始渲染之前被调用

在哪里可以使用 getStaticPaths

  • getStaticPaths 必须getStaticProps 一起使用
  • 不能getStaticPathsgetServerSideProps 一起使用
  • 你可以从同时使用 getStaticProps动态路由导出 getStaticPaths
  • 不能从非页面文件(例如你的 components 文件夹)导出 getStaticPaths
  • 你必须将 getStaticPaths 导出为独立函数,而不是页面组件的属性

在开发环境中每次请求时运行

在开发环境(next dev)中,getStaticPaths 将在每次请求时被调用。

按需生成路径

getStaticPaths 允许你通过 fallback 控制在构建期间生成哪些页面,而不是按需生成。在构建期间生成更多页面将导致构建速度变慢。

你可以通过为 paths 返回空数组来推迟按需生成所有页面。当将 Next.js 应用部署到多个环境时,这可能特别有用。例如,你可以通过按需生成所有页面来加快预览构建速度(但不用于生产构建)。这对于拥有数百/数千个静态页面的网站很有帮助。

pages/posts/[id].js
export async function getStaticPaths() {
// 当这个为 true 时(在预览环境中)不要
// 预渲染任何静态页面
// (构建更快,但初始页面加载更慢)
if (process.env.SKIP_BUILD_STATIC_GENERATION) {
return {
paths: [],
fallback: 'blocking',
}
}

// 调用外部 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 }
}