getStaticProps
导出名为 getStaticProps
的函数将在构建时使用函数返回的 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
}
您可以在顶级作用域中导入模块以在 getStaticProps
中使用。使用的导入**不会捆绑到客户端**。这意味着您可以在getStaticProps
中直接编写**服务器端代码**,包括从数据库中获取数据。
Context 参数
context
参数是一个包含以下键的对象
名称 | 描述 |
---|---|
params | 包含使用动态路由的页面的路由参数。例如,如果页面名称为[id].js ,则params 将类似于{ id: ... } 。您应该将此与getStaticPaths 一起使用,我们稍后将解释。 |
preview | (已弃用,请使用 draftMode ) 如果页面处于预览模式,则 preview 为 true ,否则为 false 。 |
previewData | (已弃用,请使用 draftMode ) 由 setPreviewData 设置的预览数据。 |
draftMode | draftMode 如果页面处于草稿模式,则为 true ,否则为 false 。 |
locale | 包含活动区域设置(如果已启用)。 |
locales | 包含所有支持的区域设置(如果已启用)。 |
defaultLocale | 包含已配置的默认区域设置(如果已启用)。 |
revalidateReason | 提供调用该函数的原因。可以是以下之一:“build”(在构建时运行),“stale”(重新验证时间段过期或在开发模式中运行),“on-demand”(通过按需重新验证触发) |
getStaticProps 返回值
getStaticProps
函数应返回一个对象,其中包含 props
、redirect
或 notFound
,以及一个**可选的** revalidate
属性。
props
props
对象是一个键值对,其中每个值都由页面组件接收。它应该是一个可序列化对象,以便传递的任何 props 都可以通过JSON.stringify
进行序列化。
export async function getStaticProps(context) {
return {
props: { message: `Next.js is awesome` }, // will be passed to the page component as props
}
}
revalidate
revalidate
属性是以秒为单位的时间,在此时间之后可以发生页面重新生成(默认为 false
或不重新验证)。
// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}
详细了解增量静态再生。
可以通过读取 x-nextjs-cache
响应标头的值来确定利用 ISR 的页面的缓存状态。可能的值如下
MISS
- 路径不在缓存中(最多发生一次,在第一次访问时)STALE
- 路径在缓存中,但超过了重新验证时间,因此将在后台更新HIT
- 路径在缓存中,并且尚未超过重新验证时间
notFound
notFound
布尔值允许页面返回 404
状态和 404 页面。当 notFound: true
时,即使之前成功生成了页面,页面也会返回 404
。这旨在支持诸如用户生成的内容被其作者删除之类的用例。请注意,notFound
遵循与 此处描述的相同的 revalidate
行为。
export async function getStaticProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json()
if (!data) {
return {
notFound: true,
}
}
return {
props: { data }, // will be passed to the page component as props
}
}
值得注意的是:对于
fallback: false
模式,不需要notFound
,因为只会预渲染getStaticPaths
返回的路径。
redirect
redirect
对象允许重定向到内部或外部资源。它应该与 { destination: string, permanent: boolean }
的结构一致。
在某些罕见情况下,您可能需要为旧的 HTTP
客户端分配自定义状态码以正确重定向。在这些情况下,您可以使用 statusCode
属性代替 permanent
属性,但不能同时使用两者。您还可以设置 basePath: false
,类似于 next.config.js
中的重定向。
export async function getStaticProps(context) {
const res = await fetch(`https://...`)
const data = await res.json()
if (!data) {
return {
redirect: {
destination: '/',
permanent: false,
// statusCode: 301
},
}
}
return {
props: { data }, // will be passed to the page component as props
}
}
如果重定向在构建时已知,则应在 next.config.js
中添加。
读取文件:使用 process.cwd()
可以在 getStaticProps
中直接从文件系统读取文件。
为此,您必须获取文件的完整路径。
由于 Next.js 将您的代码编译到一个单独的目录中,因此您不能使用 __dirname
,因为它返回的路径将与 Pages 路由器不同。
相反,您可以使用 process.cwd()
,它为您提供 Next.js 正在执行的目录。
import { promises as fs } from 'fs'
import path from 'path'
// posts will be populated at build time by getStaticProps()
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>
<h3>{post.filename}</h3>
<p>{post.content}</p>
</li>
))}
</ul>
)
}
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
const postsDirectory = path.join(process.cwd(), 'posts')
const filenames = await fs.readdir(postsDirectory)
const posts = filenames.map(async (filename) => {
const filePath = path.join(postsDirectory, filename)
const fileContents = await fs.readFile(filePath, 'utf8')
// Generally you would parse/transform the contents
// For example you can transform markdown to HTML here
return {
filename,
content: fileContents,
}
})
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts: await Promise.all(posts),
},
}
}
export default Blog
版本历史
版本 | 更改 |
---|---|
v13.4.0 | App Router 现在已稳定,并简化了数据获取 |
v12.2.0 | 按需增量静态重新生成 已稳定。 |
v12.1.0 | 添加了 按需增量静态重新生成(测试版)。 |
v10.0.0 | 添加了 locale 、locales 、defaultLocale 和 notFound 选项。 |
v10.0.0 | 添加了 fallback: 'blocking' 返回选项。 |
v9.5.0 | 稳定的 增量静态重新生成 |
v9.3.0 | 引入了 getStaticProps 。 |
这有帮助吗?