Next.js 中的 3 种渲染方式:SSR、SSG 以及 CSR
Next.js 中支持 3 种渲染方式:服务端渲染(Server-Side Rendering,简称 SSR)、静态站点渲染(Static Site Generation,简称 SSG)和客户端渲染(Client-Side Rendering,简称 CSR)。
预渲染
服务端渲染和静态站点渲染都属于“预渲染(Pre-Rendering)”。预渲染就是指在服务端完成外部数据获取以及 React 组件到 HTML 的代码转换,然后将结果网页发送到客户端。
Next.js 中的每张页面默认都会启用预渲染,也就是说网页会在发送到客户端前在服务端生成。
CSR
客户端渲染是指浏览器从服务器接收一个“空 HTML 壳子”,配合用于 hydration 的 JavaScript 代码,完成应用的初始渲染。
我们可以通过 React 的 useEffect()
或数据获取 Hook(比如 useSWR)这种客户端渲染方式来为应用程序中的组件提供数据。我分别举例子:
一、使用 useEffect()
:
import { useState, useEffect } from 'react'
function Profile() {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetch('/api/profile-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, [])
if (isLoading) return <p>Loading...</p>
if (!data) return <p>No profile data</p>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
useEffect
会在客户端 React 组件 DOM 挂载后触发,经常用来获取外部系统的数据。
二、使用 useSWR
:
import useSWR from 'swr'
const fetcher = (...args) => fetch(...args).then((res) => res.json())
function Profile() {
const { data, error } = useSWR('/api/profile-data', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
SWR 是由 Next.js 团队打造。仅需一行代码,你就可以简化项目中数据请求的逻辑,还能体验到数据缓存、请求重试、请求去重等这类实用功能。
预渲染 vs CSR
纯客户端应用在渲染时,会出现短暂白屏。预渲染应用则会立即展示构建好的首屏 HTML,不会出现白屏。
客户端渲染初始白屏问题
渲染会先生成首屏 UI,后续再激活
SSR
服务器端渲染发生在客户端每次请求后端服务时,页面 HTML 是在这个时候在服务端生成,在返回客户端。
对客户端而言,这些在服务端生成的 HTML 可以用来快速显示不具备交互能力的首屏页面。于此同时,React 会使用一起返回的 JSON 数据和 JavaScript 代码激活页面(即令页面变得可交互。例如:将事件处理程序添加给按钮),这个过程被称为hydration。
在 Next.js 中,你可以通过在页面中以命名导出 getServerSideProps
函数的方式启用服务器端渲染。Next.js 将会在每次客户端请求时调用 getServerSideProps
函数,并用函数内部返回的数据预渲染页面。
下面是一个小例子:
import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getServerSideProps: GetServerSideProps<{
repo: Repo
}> = async () => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}
export default function Page({
repo,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return repo.stargazers_count
}
SSG
在 Next.js 中,你可以通过在页面中以命名导 getStaticProps
函数的方式启用静态站点渲染。Next.js 会在构建阶段(即执行 next build
指令时)调用 getStaticProps
函数,并使用函数内部返回的数据生成静态 HTML。
静态站点渲染生成的静态 HTML 是随应用部署到服务器,因为我们在构建阶段就生成了网页内容,所以就不像服务端渲染那样,只要将静态 HTML 存储在 CDN 上,并在后续的每次请求中重复使用就行了。
下面是一个小例子:
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getStaticProps: GetStaticProps<{
repo: Repo
}> = async () => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}
export default function Page({
repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
return repo.stargazers_count
}
总结
Next.js 之美就在于你可以根据每个页面的情况选择最合适的渲染方式,无论是静态站点生成、服务器端渲染还是客户端渲染。
参考链接
- What is Rendering?, from nextjs.org
- Data Fetching, from nextjs.org
转载自:https://juejin.cn/post/7244099508212531261