getStaticPaths
如果一个页面具有动态路由并使用 getStaticProps,则需要定义要静态生成的路径列表。
当你从使用动态路由的页面导出一个名为 getStaticPaths 的函数(静态站点生成)时,Next.js 将静态预渲染 getStaticPaths 指定的所有路径。
pages/repo/[name].tsx
TypeScript
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?
如果你正在静态预渲染使用动态路由的页面,并且:
- 数据来自无头 CMS
- 数据来自数据库
- 数据来自文件系统
- 数据可以公开缓存(非用户特定)
- 页面必须预渲染(为了 SEO)并且非常快速 —
getStaticProps生成HTML和JSON文件,这两者都可以被 CDN 缓存以提高性能
getStaticPaths 何时运行
getStaticPaths 仅在生产环境构建期间运行,在运行时不会被调用。你可以使用此工具验证 getStaticPaths 内部编写的代码是否从客户端捆绑包中删除。
getStaticProps 如何与 getStaticPaths 一起运行
- 在构建期间,
getStaticProps会为构建期间返回的任何paths运行 - 使用
fallback: true时,getStaticProps在后台运行 - 使用
fallback: blocking时,getStaticProps在初始渲染之前调用
我可以在哪里使用 getStaticPaths
getStaticPaths必须与getStaticProps一起使用- 你不能将
getStaticPaths与getServerSideProps一起使用 - 你可以从使用
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 }
}