跳到内容

getStaticProps

如果你从页面导出一个名为 getStaticProps (静态站点生成) 的函数,Next.js 将会在构建时使用 getStaticProps 返回的 props 预渲染此页面。

pages/index.tsx
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
}

请注意,无论渲染类型如何,任何 props 都将传递给页面组件,并且可以在客户端初始 HTML 中查看。这是为了允许页面正确地进行水合 (hydration)。请确保你不要在 props 中传递任何不应在客户端上可用的敏感信息。

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

我应该何时使用 getStaticProps?

如果满足以下条件,你应该使用 getStaticProps

  • 渲染页面所需的数据在构建时即可获得,早于用户的请求
  • 数据来自无头 CMS
  • 页面必须预渲染(为了 SEO)并且速度非常快 —— getStaticProps 生成 HTMLJSON 文件,这两者都可以被 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 获取博客文章列表。

pages/blog.tsx
// posts will be populated at build time by getStaticProps()
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</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() {
  // Call an external API endpoint to get posts.
  // You can use any data fetching library
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

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

直接编写服务器端代码

由于 getStaticProps 仅在服务器端运行,因此它永远不会在客户端运行。它甚至不会包含在浏览器的 JS 包中,因此你可以直接编写数据库查询,而无需将它们发送到浏览器。

这意味着,你可以直接在 getStaticProps 中编写服务器端代码,而不是从 getStaticProps 中获取API 路由(API 路由本身从外部源获取数据)。

以下示例说明了这一点。API 路由用于从 CMS 获取一些数据。然后直接从 getStaticProps 调用该 API 路由。这会产生额外的调用,降低性能。相反,可以通过使用 lib/ 目录来共享从 CMS 获取数据的逻辑。然后它可以与 getStaticProps 共享。

lib/load-posts.js
// The following function is shared
// with getStaticProps and API routes
// from a `lib/` directory
export async function loadPosts() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts/')
  const data = await res.json()
 
  return data
}
pages/blog.js
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
 
// This function runs only on the server side
export async function getStaticProps() {
  // Instead of fetching your `/api` route you can call the same
  // function directly in `getStaticProps`
  const posts = await loadPosts()
 
  // Props returned will be passed to the page component
  return { props: { posts } }
}

或者,如果你使用 API 路由来获取数据,那么 fetch() API *可以* 直接在 getStaticProps 中使用以获取数据。

要验证 Next.js 从客户端包中移除的内容,您可以使用 next-code-elimination 工具

静态生成 HTML 和 JSON

当使用 getStaticProps 的页面在构建时预渲染时,除了页面 HTML 文件外,Next.js 还会生成一个 JSON 文件,其中包含运行 getStaticProps 的结果。

此 JSON 文件将用于通过 next/linknext/router 进行客户端路由。当您导航到使用 getStaticProps 预渲染的页面时,Next.js 会获取此 JSON 文件(在构建时预先计算)并将其用作页面组件的 props。这意味着客户端页面转换将不会调用 getStaticProps,因为仅使用导出的 JSON。

当使用增量静态生成时,getStaticProps 将在后台执行,以生成客户端导航所需的 JSON。您可能会看到针对同一页面的多个请求,但这属于预期行为,并且不会影响最终用户性能。

我在哪里可以使用 getStaticProps

getStaticProps 只能从页面导出。您不能从非页面文件、_app_document_error 导出它。

此限制的原因之一是 React 需要在页面渲染之前拥有所有必需的数据。

此外,您必须将 getStaticProps 作为独立函数导出 — 如果您将 getStaticProps 添加为页面组件的属性,则它不会工作。

须知:如果您创建了自定义应用,请确保将 pageProps 传递给页面组件,如链接文档所示,否则 props 将为空。

在开发环境中,每次请求都会运行

在开发环境 (next dev) 中,每次请求都会调用 getStaticProps

预览模式

您可以使用预览模式临时绕过静态生成,并在请求时而不是构建时渲染页面。例如,您可能正在使用无头 CMS,并希望在发布之前预览草稿。