浏览器的三种渲染方式
三种渲染方式
在从获取数据到生成 HTML 并展示到浏览器的过程中,主要有三种渲染方式,分别为:SSG,SSR和CSR。 简单介绍一下
- SSG:静态站点生成,即在构建阶段就提前生成所有页面的静态HTML文件。可以部署在静态服务器,用户访问时直接获取现成的HTML。
- SSR:服务端渲染。在每次用户请求页面时,由服务器执行代码生成完整的HTML,再返回给浏览器。
- CSR:客户端渲染。服务器仅返回一个基础的HTML,浏览器下载JS后,由JS在客户端执行渲染。
站点的渲染模式
最初设计网站的文章详情页时,采用的是SSG策略。虽然应用了next的动态路由,但是是先使用next的generateStaticParams()方法提前获取并生成了所有可能的路由,访问时会返回构建时就生成好的页面。这样主要是简单,并且性能和SEO都很好。
最近我打算扩展一下网站的功能,于是将所有文章数据迁移到了云数据库,并重写了SSR渲染的逻辑。现在每次请求时服务器都会先从数据库中请求相关数据,使用该数据生成HTML,然后发送给浏览器。更改完后运行没什么问题,就是,比以前进入页面会稍微慢一点(在优化啦!)
混用SSR和CSR
这个网站的很多过渡动画我是用motion库做的,motion动画依赖于浏览器环境,因此组件必须声明为"use client"。这就会涉及到混用SSR和CSR的问题。实现其实很简单:最外层的page.tsx文件保持默认的Server Component,在里面添加从数据库读取数据的逻辑;独立写一个客户端组件的文件,通过props将数据传给客户端组件。这样就成功将CSR组件嵌套在SSR组件里,实现整体了SSR。
//page.tsx
export default async function Page() {
async function connect_db({
//数据库读取逻辑
})
const data = await connect_db()
//这里也可以直接传普通服务端函数
return <ClientComponent data={data} />
}
另外,如果希望在客户端组件调用Server Action(use server下的函数),例如表单处理绑定给action的函数,应该直接在use client文件中导入在另外的use server文件中定义的处理函数而非使用props。
这是因为next会在构建阶段对Server Action进行静态分析和绑定,为它们生成唯一的调用标识,用于被静态识别后引用。简单来说,就是所有使用 Server Action 的组件必须在编译时就能确定引用到哪个 action。
"use client"
import { process_data } from "@/lib/process_data"
export default function ClientComponent() {
return (
<form action={process_data}>
<input type="text"></input>
</form>
)
}