getStaticPaths

如果页面使用了 动态路由 (Dynamic Routes) 并配合 getStaticProps,则需要定义需要静态生成的路径列表。

当您从使用动态路由的页面导出一个名为 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
}

getStaticPaths API 参考文档 涵盖了可与 getStaticPaths 一起使用的所有参数和属性。

何时应该使用 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动态路由 (Dynamic Route) 导出 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 }
}

On this page