<
Next.js中的预渲染
>
上一篇

敏捷框架:Scrum
下一篇

使用Nginx把React项目部署到服务器
Pre-rendering of Next.js

在默认情况下,Next.js 会预渲染每个页面。这意味着 Next.js 会提前为每个页面生成 HTML,而不是全部由客户端 JavaScript 完成。预渲染可以带来更好的性能和SEO(Search engine optimization,搜索引擎优化)。

每个生成的 HTML 都与该页面所需的最少 JavaScript 代码相关。当浏览器加载页面时,其 JavaScript 代码将运行并使页面完全交互。(这个过程称为hydration水合作用。)

Next.js的预渲染分为两种形式:Static GenerationServer-side Rendering。其中, Static Generation 又分为 with data, 和 without data 两种情况。接下来我会分别讲讲每一种情况。

Static Generation和 Server-side Rendering

Next.js 有两种pre-rendering形式,Static Generation和 Server-side Rendering,以下是官方的解释:

开发模式下(运行npm run devyarn dev时),页面在每次request的时候预渲染。 这也适用于静态生成,使其更易于开发。 投入生产时,静态生成将在构建时发生一次,而不是在每次请求时发生。

我们可以分别为每个page设置pre-rendering形式

你应该问问自己:“我可以在用户请求之前预渲染此页面吗?” 如果答案是肯定的,那么你应该选择Static Generation

Static Generation

Static Generation can be done with and without data. 静态生成有以下两种pre-rendering方式:

Static Generation with data

对于某些页面,如果不首先获取一些外部数据,可能无法呈现 HTML。也许需要在构建时访问文件系统、获取外部 API 或查询数据库。Next.js开箱即用地支持这种情况——带数据的静态生成

Image about Static Generation with Data From Next.js Document

方法: getStaticProps

在 Next.js 中,导出页面组件时,你可以导出一个名为getStaticPropsasync function(异步函数)。

例如:

export default function Home(props) { ... }

export async function getStaticProps() {
  // Get external data from the file system, API, DB, etc.
  const data = ...

  // The value of the `props` key will be
  //  passed to the `Home` component
  return {
    props: ...
  }
}

这是一段官网解释:

Essentially, getStaticProps allows you to tell Next.js: “Hey, this page has some data dependencies — so when you pre-render this page at build time, make sure to resolve them first!”

Note: In development modegetStaticProps  runs on each request instead.

从API拿数据

export async function getSortedPostsData() {
  // Instead of the file system,
  // fetch post data from an external API endpoint
  const res = await fetch('..');
  return res.json();
}

从数据库拿数据

import someDatabaseSDK from 'someDatabaseSDK'

const databaseClient = someDatabaseSDK.createClient(...)

export async function getSortedPostsData() {
  // Instead of the file system,
  // fetch post data from a database
  return databaseClient.query('SELECT posts...')
}

getStaticProps在服务器端运行。它永远不会在客户端运行。它甚至不会包含在浏览器的 JS 包中。这意味着你可以编写直接数据库查询等代码,而无需将它们发送到浏览器。

开发npm run devyarn dev)中,getStaticProps每个请求(request) 上运行。 在生产中,getStaticProps构建时 运行。但是,可以使用getStaticPaths返回的fallback key 来增强此行为

getStaticProps只能从page导出。不能从non-page文件中导出它。

Static Generation with data 总结

由于静态生成build 时发生一次,因此它不适合频繁更新或根据每个用户请求更改的数据。

如果你的数据可能会发生变化,你可以使用服务器端渲染

Server-side Rendering With Data

为了使用 Server-side Rendering 你需要从页面导出 getServerSideProps 方法 而不是之前 提到的 getStaticProps 方法。

仅当你需要预渲染的数据必须在请求时获取,才应使用getServerSideProps。 这么做,用户接收到页面第一个字节所花费的时间time to first byte (TTFB) 会比 getStaticProps 长,因为服务器要计算每一个request的结果, 并且如果没有额外配置, CDN无法缓存结果。

export async function getServerSideProps(context) {
  return {
    props: {
      // props for your component
    },
  };
}

getServerSideProps在请求时被调用,它的参数 ( context) 包含请求特定的参数。

如果不需要预渲染data, 指仅预渲染page,可能由于data时效性要求很高,不需要预渲染data,也可以使用Client-side Rendering ,比如,在dashboard用户仪表板场景中,dashboard是私有的、特定于用户的页面,所以 SEO不相关,且不需要在服务器端预渲染(不知道用户信息,预渲染无意义);数据更新频繁,需要请求时取数据。

Client-side Rendering

适用场景

与 SEO 无关的私人的、用户特定的页面

适应场景举例

比如,在dashboard用户仪表板场景中,dashboard是私有的、特定于用户的页面,所以 SEO不相关,且不需要在服务器端预渲染(不知道用户信息,预渲染无意义);数据更新频繁,需要请求时取数据。

SWR

如果在客户端获取数据,可以使用Next.js团队出的SWR,这是一个React Hook,它处理缓存、重新验证、焦点跟踪、间隔重新获取等。

示例:

import useSWR from 'swr';

function Profile() {
  const { data, error } = useSWR('/api/user', fetch);

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;
  return <div>hello {data.name}!</div>;
}

查看SWR 文档以了解更多信息。

Top
Foot