Next.js Prerendering
2023-08-27Next.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。