getStaticProps
如果从页面导出一个名为 getStaticProps
的函数(静态站点生成),Next.js 将在构建时使用该函数返回的 props 预渲染此页面。
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
type Repo = {
name: string
stargazers_count: number
}
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 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
}
请注意,无论渲染类型如何,任何
props
都会传递给页面组件,并可以在初始 HTML 的客户端查看。这是为了让页面能够正确进行 hydrate。请确保不要在props
中传递任何不应在客户端可用的敏感信息。
getStaticProps
API 参考文档 涵盖了可与 getStaticProps
一起使用的所有参数和 props。
何时应使用 getStaticProps?
在以下情况下应使用 getStaticProps
:
- 渲染页面所需的数据在用户请求之前的构建时可用
- 数据来自无头 CMS
- 页面必须预渲染(为了 SEO)且速度非常快 ——
getStaticProps
会生成HTML
和JSON
文件,两者都可以通过 CDN 缓存以提高性能 - 数据可以公开缓存(非用户特定)。在某些特定情况下,可以通过使用中间件重写路径来绕过此条件
getStaticProps 何时运行
getStaticProps
始终在服务端运行,而不会在客户端运行。您可以使用 此工具 验证 getStaticProps
内的代码已从客户端包中移除。
getStaticProps
始终在next build
期间运行- 使用
fallback: true
时,getStaticProps
会在后台运行 - 使用
fallback: blocking
时,getStaticProps
会在初始渲染前调用 - 使用
revalidate
时,getStaticProps
会在后台运行 - 使用
revalidate()
时,getStaticProps
会在后台按需运行
与 增量静态再生 结合使用时,getStaticProps
会在重新验证过期页面的同时在后台运行,并将新页面提供给浏览器。
getStaticProps
无法访问传入的请求(如查询参数或 HTTP 头),因为它生成的是静态 HTML。如果您的页面需要访问请求,请考虑在使用 getStaticProps
的同时使用 中间件。
使用 getStaticProps 从 CMS 获取数据
以下示例展示如何从 CMS 获取博客文章列表。
// posts 将在构建时由 getStaticProps() 填充
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// 此函数在构建时在服务端调用
// 不会在客户端调用,因此甚至可以
// 直接执行数据库查询
export async function getStaticProps() {
// 调用外部 API 端点获取文章
// 可以使用任何数据获取库
const res = await fetch('https://.../posts')
const posts = await res.json()
// 通过返回 { props: { posts } },Blog 组件
// 将在构建时接收 `posts` 作为 prop
return {
props: {
posts,
},
}
}
// posts 将在构建时由 getStaticProps() 填充
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// 此函数在构建时在服务端调用
// 不会在客户端调用,因此甚至可以
// 直接执行数据库查询
export async function getStaticProps() {
// 调用外部 API 端点获取文章
// 可以使用任何数据获取库
const res = await fetch('https://.../posts')
const posts = await res.json()
// 通过返回 { props: { posts } },Blog 组件
// 将在构建时接收 `posts` 作为 prop
return {
props: {
posts,
},
}
}
getStaticProps
API 参考文档 涵盖了可与 getStaticProps
一起使用的所有参数和 props。
直接编写服务端代码
由于 getStaticProps
仅在服务端运行,因此它永远不会在客户端运行。它甚至不会包含在浏览器的 JS 包中,因此您可以编写直接的数据库查询而无需担心它们被发送到浏览器。
这意味着,与其从 getStaticProps
中获取 API 路由(该路由本身从外部源获取数据),不如直接在 getStaticProps
中编写服务端代码。
请看以下示例。API 路由用于从 CMS 获取一些数据,然后直接从 getStaticProps
调用该 API 路由。这会产生额外的调用,降低性能。相反,可以通过使用 lib/
目录共享从 CMS 获取数据的逻辑,然后与 getStaticProps
共享。
// 以下函数与 getStaticProps 和 API 路由
// 共享,位于 `lib/` 目录中
export async function loadPosts() {
// 调用外部 API 端点获取文章
const res = await fetch('https://.../posts/')
const data = await res.json()
return data
}
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
// 此函数仅在服务端运行
export async function getStaticProps() {
// 无需获取 `/api` 路由,可以直接
// 在 `getStaticProps` 中调用相同的函数
const posts = await loadPosts()
// 返回的 props 将传递给页面组件
return { props: { posts } }
}
或者,如果您 没有 使用 API 路由来获取数据,则可以直接在 getStaticProps
中使用 fetch()
API 获取数据。
要验证 Next.js 从客户端包中移除了哪些内容,可以使用 next-code-elimination 工具。
静态生成 HTML 和 JSON
当使用 getStaticProps
的页面在构建时预渲染时,除了页面 HTML 文件外,Next.js 还会生成一个包含 getStaticProps
运行结果的 JSON 文件。
此 JSON 文件将通过 next/link
或 next/router
用于客户端路由。当导航到使用 getStaticProps
预渲染的页面时,Next.js 会获取此 JSON 文件(在构建时预计算)并将其用作页面组件的 props。这意味着客户端页面转换 不会 调用 getStaticProps
,因为只使用导出的 JSON。
使用增量静态生成时,getStaticProps
将在后台执行以生成客户端导航所需的 JSON。您可能会看到对同一页面的多个请求,但这是预期的,不会影响最终用户的性能。
可以在何处使用 getStaticProps
getStaticProps
只能从 页面 导出。不能从非页面文件、_app
、_document
或 _error
导出。
此限制的原因之一是 React 需要在页面渲染之前拥有所有必需的数据。
此外,必须将 getStaticProps
作为独立函数导出 —— 如果将其作为页面组件的属性添加,它将 不会 工作。
须知:如果您创建了 自定义应用,请确保按照链接文档中的说明将
pageProps
传递给页面组件,否则 props 将为空。
开发环境中的每次请求运行
在开发环境 (next dev
) 中,getStaticProps
会在每次请求时调用。
预览模式
您可以使用 预览模式 临时绕过静态生成,在 请求时 而非构建时渲染页面。例如,您可能正在使用无头 CMS 并希望在草稿发布前预览它们。