Blitz 尚在 beat 阶段! 🎉 预计会在今年的 Q3 季度发布 1.0
Back to Documentation Menu

getStaticPaths API

Topics

Jump to a Topic

如果一个页面有动态路由(文档)并且使用 getStaticProps,则需要定义在构建过程中必须渲染为 HTML 的路径列表。

如果你从使用动态路由的页面中导出一个称为 getStaticPropsasync 函数 ,Blitz 将静态地预渲染 getStaticPaths 指定的所有路径。

export async function getStaticPaths() {
  return {
    paths: [
      { params: { ... } } // 查阅下方 "paths" 章节
    ],
    fallback: true or false // 查阅下方 "fallback" 章节
  };
}

paths 键(必须)

paths 键确定了哪些路径将被预渲染。例如,假设你有一个页面使用动态路由的名 为 app/posts/pages/posts/[id].js 的文件。如果你从这个页面导出 getStaticPaths 并为 path 返回以下内容:

return {
  paths: [
    { params: { id: '1' } },
    { params: { id: '2' } }
  ],
  fallback: ...
}

那么 Blitz 将会在 app/posts/pages/posts/[id].js 页面组件的构建过程中静态 生成 posts/1posts/2

请注意,每个 params 的值必须与页面名称中使用的参数匹配:

  • 如果页面的名称是 app/posts/pages/posts/[postId]/[commentId],那么 params 应该包括 postIdcommentId
  • 如果页面名称使用捕获所有路由的模式,例如 pages/[...slug],那么 params 应该包含值为数组的 slug。例如,如果这个数组是 ['foo', 'bar'],那么 Blitz 会为 /foo/bar 静态生成页面。
  • 如果页面使用一个可选的捕获所有路由的模式,可提供 null[]undefinedfaluse 来渲染最根目录的路由。例如,如果你 为 pages/[[...slug]] 提供 slug: false,Blitz 会静态生成页面 /

fallback 键(必须)

getStaticPaths 返回的对象必须包含一个布尔值的 fallback 键。

fallback: false

如果 fallbackfalse,那么没有被 getStaticPaths 返回的任何路径将会 导致一个 404 页面。当你有一个数量少的路径来渲染的时候可以这么做——因此 这些是在构建过程中静态生成的。当新的页面不常被更新的时候也会很有用。如果你 要为数据源新增很多元素并且需要渲染新的页面,你最好再次执行构建。

这是一个 app/posts/pages/posts/[id].js 示例,其中每页渲染一个博客文章。 博客文章的类别将从你的数据库或 CMS 获取,并由 getStaticPaths 返回。接着 ,针对每个页面,使用 getStaticPaths 获取单个文章的数据。

// app/posts/pages/posts/[id].js

function Post({post}) {
  // 渲染文章...
}

// 该函数在预渲染时被调用
export async function getStaticPaths() {
  // 1. 使用 blitz query 来获取所有文章
  // 2. 或调用外部 API 端口来获取文章
  const posts = /* ... */

  // 基于 posts 获取我们想要预渲染的路径
  const paths = posts.map((post) => ({
    params: {id: post.id},
  }))

  // 我们将只在构建过程中预渲染这些路径
  // { fallback: false } 意味着其它路由将会 404。
  return {paths, fallback: false}
}

// 这个也在构建过程中被调用
export async function getStaticProps({params}) {
  // params 包含文章 `id`。
  // 如果路由像 /posts/1 这样,那么 params.id 就是 1
  const post = /* get one post */

  // 通过 props 来传递文章数据到页面中
  return {props: {post}}
}

export default Post

fallback: true

如果 fallbacktrue,那么 getStatickProps 改变时的行为是:

  • getStaticPaths 返回的路径将会在构建过程中被渲染为 HTML。
  • 在构建过程中没有没生成的路径将不会导致一个 404 页面。反之,Blitz 将 会提供一个页面在第一次请求到这个路径(查阅下方的 “预备页面“来了解更多)时的“fallback”版本。
  • 在背后,Blitz 将静态生成请求的路径 HTML 和 JSON。其中包括运行 getStaticProps
  • 当上述结束,浏览器将接收到生成路径的 JSON。这将被用来自动渲染具有所需 props 的页面。从用户的角度来看,该页面将从预备页面切换到整页。
  • 与此同时,Blitz 将此路径添加到预渲染页面的列表中。对相同路径的后续请求, 将提供已生成的页面,就像在构建时预渲染的其他页面一样。

预备页面

在页面的 “fallback” 版本中:

  • 页面的 props 将为空。
  • 使用 路由,你可以检测到是否正在渲染 fallback,router.isFallback 将会为 true

这是一个使用 isFallback 的示例:

// app/posts/pages/posts/[id].js
import {useRouter} from "blitz"

function Post({post}) {
  const router = useRouter()

  // 如果当前页面还没被生成,则将最初显示如下加载动画,直到 `getStaticProps` 运行完成为止。
  if (router.isFallback) {
    return <div>Loading...</div>
  }

  // 渲染文章...
}

// 该函数在构建过程中被调用
export async function getStaticPaths() {
  return {
    // 仅仅 `/posts/1` 和 /posts/2/ 在构建过程中被生成。
    paths: [{params: {id: "1"}}, {params: {id: "2"}}],
    // 启用静态生成额外页面:
    // 例如:`/posts/3`
    fallback: true,
  }
}

// 这也在构建过程中被调用
export async function getStaticProps({params}) {
  // 参数包含文章 `id`。
  // 如果路由像 /posts/1,那么 params.id 是 1
  const post = /* ... */

  // 通过 props 来传递文章数据到页面中
  return {props: {post}}
}

export default Post

fallback: true 什么时候有用?

如果你的应用具有大量依赖于数据的静态页面(请想象:一个很大的电商网站)时 ,fallback: true 将会很有用。你想要预渲染所有产品页面的话,你的构建过程 将会非常之久。

相反,你可以静态生成页面的一小部分,其余部分使用 fallback: true。当有人 请求尚未生成的页面时,用户将看到带有加载动画的页面。此后不久 ,getStaticProps 完成,此页面将使用刚请求的数据渲染。从现在开始,请求同 一个页面的每个人都将获得静态预渲染的页面。

这可以确保用户在保持快速构建的同时始终能获得快速的体验,并获得“静态生成”的 好处。

fallback: true 将不会 更新 生成的页面,相关请查 阅增量静态再生

fallback: 'blocking'

如果 fallback'blocking',新的没有被 getStaticPaths 返回的路径将 生成 HTML,该 HTML 与 SSR 相同(因此为何 blocking),然后被缓存以用于将 来的请求,因此每个路径仅产生一次。

getStaticProps 的表现形式如下:

  • getStaticPath 返回的路径将被 getStaticProps 在构建过程渲染为 HTML。
  • 构建过程中没有被生成的路由将不会导致 404 页面。反而 Blitz 将会对第一 个请求进行 SSR 并返回生成的 HTML。
  • 完成后,浏览器将接收生成路径的 HTML。从用户的角度来看,它将从“浏览器正在 请求页面”过渡到“已加载整个页面”。没有加载/预备状态的页面闪烁。
  • 与此同时,Blitz 添加这个路径到预渲染页面的列表中。对同一路径的后续请求将 提供已渲染好的页面,就像在构建过程中预渲染的其他页面一样。

fallback: 'blocking' 将默认不会更新已生成的页面。要更新已生成的页面 ,请结合使 用增量静态再生fallback: 'blocking'

我什么时候可以使用 getStaticPaths?

如果你要静态预渲染使用动态路由的页面,则应使用 getStaticPaths

TypeScript:使用 GetStaticPaths

对于 TypeScript,你可以使用 blitz 中的 GetStaticPaths 类型:

import { GetStaticPaths } from "blitz"

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

技术细节

getStaticProps 搭配使用

当你在有动态路由参数的页面中使用 getStaticProps 时,你必须使用 getStaticPaths

你无法和 getServerSideProps 一起使用 getStaticPaths

仅在服务端构建过程中执行

getStaticPaths 仅在服务端构建过程中执行。

仅在页面中支持

getStaticPaths 仅能从一个页面中导出。你无法从一个非页面文件中导出。

同时,你必须使用 export async function getStaticPaths() {}——如果你将 getStaticPaths 作为一个页面组件的属性,它将不能运行。

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

在开发环境中(blitz dev),getStaticPaths 将会在每一次请求中被调用。


Idea for improving this page? Edit it on GitHub.