Next.js Prerendering

2023-08-27

Next.js 的两种预渲染技术:SSG (Static Site Generation) 和 SSR (Server-side Rendering)。他们的区别在于是何时生成 HTML。

  • SSG:在 build time 生成 HTML(也可配置为在 run time 生成),并且此 HTML 会被每个请求复用,适合 Blog、站点首页和文档等静态页面使用。
  • SSR:为每个请求渲染不同 HTML。

BTW,SSG 和 SSR (和客户端渲染)可以在应用中根据需要混合使用,且无论是否使用 SSG or SSR,Next.js 都会默认开启预渲染,服务端首次返回的是正确的 HTML。

预渲染 vs. 单页面 SPA

预渲染的好处是服务端首次返回的 HTML 是正确的(利于 SEO),这意味着在禁用 JS 的客户端环境下,页面任然可以正常展示,只有交互逻辑无法正常执行。

单页面应用服务端返回的 HTML 是一个空壳,强依赖客户端 JS 代码来渲染页面,禁用 JS 时页面无法正常展示。

SSR & SSG 预渲染原理

通过 getServerSideProps 或 getStaticProps 在服务端渲染 HTML 页面,所以服务端首次返回的 HTML 是正确的。并且在 HTML 中插入 id 为__NEXT_DATA__<script>,客户端 JS 取出 <script> 中的 json props 重新渲染页面(Hydration),使交互逻辑可以正常执行。

SSR or SSG 应用代码

export default function SSR({ username }) {
  return (
    <>
      <h1> Hello {username} </h1>
    </>
  )
}

// export async function getServerSideProps() {
//   return {
//     props: {
//       username: "Sawyer"
//     },
//   };
// }

export async function getStaticProps() {
  return {
    props: {
      username: "Sawyer"
    }
  }
}

Html 返回:

<!DOCTYPE html>
<html lang="en">
    <head>
      ... 省略 head 部分
  	</head>
    <body>
        <div id="__next">
            <h1>
              Hello Sawyer
            </h1>
        </div>
        <script src="/_next/static/chunks/react-refresh.js?ts=1693117005929"></script>
        <script id="__NEXT_DATA__" type="application/json">
            {"props":{"pageProps":{"username":"Sawyer"},"__N_SSP":true},"page":"/ssr","query":{},"buildId":"development","isFallback":false,"gssp":true,"scriptLoader":[]}
        </script>
    </body>
</html>

FAQ

useEffect 与 预渲染

预渲染期间 React useEffect 不会执行。只有在触发页面渲染 DOM 时,useEffect 才会执行,服务端渲染不会渲染 DOM。

References

预渲染服务端 API

pre-rendering