introduction

从v9.3.0开始才支持这个函数 …

暴露一个函数叫做getStaticProps将在构建时预渲染一个页面(使用从这个函数返回的属性) …

  1. export async function getStaticProps(context) {
  2. return {
  3. props: {}, // will be passed to the page component as props
  4. }
  5. }

你能够在页面顶级范围内导入模块getStaticProps,使用的导入将不会打包到客户端 .. 这意味着你能够直接在getStaticProps中写服务端代码,包括从数据库中抓取数据 ..

上下文参数

上下文参数包含以下key:

  • params包含了页面的路由参数(如果使用了动态路由) .. 例如页面名称是[id].js,那么params将会看起来像{id: ....},你应该使用getStaticPaths进行结合 …
  • preview = true,那么这个页面位于预览模式,否则 undefined
  • previewData包含了由setPreviewData设置的预览数据 ..
  • locale包含了激活的locale( 如果启用) ..
  • locales包含了所有支持的locales ..(如果启用) ..
  • defaultLocale包含了配置的默认locale (如果启用) ..

返回值

返回值应该包含要么props,redirect,notFound(并跟随一个可选的revalidate属性) ..

  • props

这个对象是一个key-value 对,每一个值都会被页面组件接收 .. 它应该是一个可序列化对象(因此对于任何传递的props,都能够被JSON.stringify序列化 ..

  • revalidate

这个属性考虑到多少秒之后那个页面进行重新生成 ..(默认的false或者 没有重新验证) …

  1. // This function gets called at build time on server-side.
  2. // It may be called again, on a serverless function, if
  3. // revalidation is enabled and a new request comes in
  4. export async function getStaticProps() {
  5. const res = await fetch('https://.../posts')
  6. const posts = await res.json()
  7. return {
  8. props: {
  9. posts,
  10. },
  11. // Next.js will attempt to re-generate the page:
  12. // - When a request comes in
  13. // - At most once every 10 seconds
  14. revalidate: 10, // In seconds
  15. }
  16. }

详情了解增量静态重新生成 ..

利用了ISR的这个页面的缓存状态 能够通过阅读x-nextjs-cache响应头进行决定, 可能的值如下:

  • MISS 路径不存在于缓存中(最开始出现一次,第一次参观)
  • STALE存在于缓存中(但是溢出了最大验证时间,因此将在后台进行更新) ..
  • HIT 路径存在于缓存中,相当于命中了 ..

notFound

这个值允许页面返回404状态码和404页面,使用true,这个页面将会返回一个404(即时之前成功生成了页面),这意味着打算支持之前由用户创建的数据(但是现在被移除了),notFound允许相同的revalidate行为 ….

  1. export async function getStaticProps(context) {
  2. const res = await fetch(`https://.../data`)
  3. const data = await res.json()
  4. if (!data) {
  5. return {
  6. notFound: true,
  7. }
  8. }
  9. return {
  10. props: { data }, // will be passed to the page component as props
  11. }
  12. }

注意到notFound 对于fallback:false模式是不需要的(因为仅仅从getStaticPaths中返回的路径才能够被预渲染) …

重定向

redirect对象允许重定向到内部或者外部资源 ,它应该匹配{destination: string,permanent: boolean}

在某些极少情况下,你需要自定义状态码(对于旧的HTTP客户端为了正确的重定向),在这些情况下,你能够使用statusCode替代permanent属性,但是不需要同时使用,你能够next.config.js 设置basePath: false … 它类似于重定向 …

  1. export async function getStaticProps(context) {
  2. const res = await fetch(`https://...`)
  3. const data = await res.json()
  4. if (!data) {
  5. return {
  6. redirect: {
  7. destination: '/',
  8. permanent: false,
  9. // statusCode: 301
  10. },
  11. }
  12. }
  13. return {
  14. props: { data }, // will be passed to the page component as props
  15. }
  16. }

如果在构建时已知的重定向,它们应该增加到next.config.js 链接中进行替代 ..

使用process.cwd()读取文件

从文件系统中可以直接读取文件信息

为了这样做需要拿到文件的完整路径 ..

因为Next.js 编译了代码到单独的目录(不能够直接使用__dirname作为路径,它将返回不同于page 目录的路径)

所以我们通过process.cwd() 去获取Next.js 当前执行的目录路径

  1. import { promises as fs } from 'fs'
  2. import path from 'path'
  3. // posts will be populated at build time by getStaticProps()
  4. function Blog({ posts }) {
  5. return (
  6. <ul>
  7. {posts.map((post) => (
  8. <li>
  9. <h3>{post.filename}</h3>
  10. <p>{post.content}</p>
  11. </li>
  12. ))}
  13. </ul>
  14. )
  15. }
  16. // This function gets called at build time on server-side.
  17. // It won't be called on client-side, so you can even do
  18. // direct database queries.
  19. export async function getStaticProps() {
  20. const postsDirectory = path.join(process.cwd(), 'posts')
  21. const filenames = await fs.readdir(postsDirectory)
  22. const posts = filenames.map(async (filename) => {
  23. const filePath = path.join(postsDirectory, filename)
  24. const fileContents = await fs.readFile(filePath, 'utf8')
  25. // Generally you would parse/transform the contents
  26. // For example you can transform markdown to HTML here
  27. return {
  28. filename,
  29. content: fileContents,
  30. }
  31. })
  32. // By returning { props: { posts } }, the Blog component
  33. // will receive `posts` as a prop at build time
  34. return {
  35. props: {
  36. posts: await Promise.all(posts),
  37. },
  38. }
  39. }
  40. export default Blog

使用TypeScript

你能够使用来自nextGetStaticProps的类型

  1. import { GetStaticProps } from 'next'
  2. export const getStaticProps: GetStaticProps = async (context) => {
  3. // ...
  4. }

如果你想要推断类型,使用InferGetStaticPropsType ..

  1. import { InferGetStaticPropsType } from 'next'
  2. type Post = {
  3. author: string
  4. content: string
  5. }
  6. export const getStaticProps = async () => {
  7. const res = await fetch('https://.../posts')
  8. const posts: Post[] = await res.json()
  9. return {
  10. props: {
  11. posts,
  12. },
  13. }
  14. }
  15. function Blog({ posts }: InferGetStaticPropsType<typeof getStaticProps>) {
  16. // will resolve posts to type Post[]
  17. }
  18. export default Blog