Rendering
客户端渲染 (Client Side Rendering)
- 浏览器发起请求
- 服务器返回HTML/JS/CSS等文件
- JS动态渲染生成DOM
- 浏览器渲染DOM
- 交互流畅,可直接响应
- 前后端分离,前端注重UI,后端注重数据
- 首屏加载慢,因为需要下载JS/CSS等文件
- SEO不友好,因为JS动态渲染
- 后台管理系统开发
- 单页面应用开发 (SPA)
服务端渲染 (Server Side Rendering)
- 浏览器发起请求
- 服务器(内部调用API接口->渲染HTML页面)
- 浏览器读取HTML页面并加载JS/CSS等文件
- 执行水合
- 首屏加载快,因为服务器已经渲染了HTML页面
- SEO友好,搜索引擎能爬取到完整内容
import { JSDOM } from "jsdom";import fs from "node:fs";
const dom = new JSDOM(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="app"></div> </body> </html>`);
const document = dom.window.document;const app = document.querySelector("#app");
fetch("https://api.github.com/users") .then((res) => res.json()) .then((data) => { console.log(data); app.innerHTML = data.forEach((user) => { const div = document.createElement("div"); div.innerHTML = user.login; app.appendChild(div); }); fs.writeFileSync("index.html", dom.serialize()); });- 服务器承担渲染工作,如果用户访问量大,对服务器配置要求高,增大成本
- 企业官网
- 电商网站
- 博客网站
静态站点生成 (Static Side Generation)
Next.js use generateStaticParams()
- 项目构建
npm run build - 生成静态文件 (路由对应HTML页面)
- 部署到Nginx或CDN
- 浏览器发起请求
- 服务器返回HTML页面
- 水合
- Better Performance
- Server has less load
- Instant page load
- Not suitable for Dynamic Content
(Incremental Static Regeneration)
"use server";
export const createPost = async (formData: FormData) => { const title = formData.get("title") as string; const content = formData.get("content") as string;
await prisma.post.create({ data: { title, content, slug: title.toLowerCase().replace(/ /g, "-"), }, });
// look here revalidatePath("/blog");};(Partial Prerendering)
HTML页面是静态的,需要通过JS才能变成动态的,不然HTML是没有任何交互效果的,当JS下载完成在赋予HTML交互效果的阶段称之为水合
Next.js水合
Section titled “Next.js水合”- HTML structure
- CSS design
- JavaScript for hydration
- Client part of React & Next.js
- RSC payload
- Next.js 服务器接收到用户请求
- 服务器执行 React 组件代码,获取数据 (比如从 API 接口请求文章列表)
- 服务器将 React 组件渲染成静态 HTML 字符串 (包含了文章列表的所有内容)
- 服务器将这个 HTML 字符串返回给浏览器
- 浏览器接收到 HTML,立即解析并展示给用户 (此时用户能看到文章列表,但点击 “查看详情” 按钮没有反应)
- 浏览器开始下载页面所需的 JS 文件 (包括 React 核心库、组件代码等)
- JS 下载完成后,React 会执行
ReactDOM.hydrateRoot()方法 (在 React 18+ 中) hydrateRoot()会对比浏览器中的真实 DOM 和 React 组件的虚拟 DOM- 如果结构一致,React 会给真实 DOM 绑定事件监听器
- 如果发现差异 (比如服务器和客户端数据不一致),React 会发出警告,并以客户端渲染的结果为准
- 水合完成后,页面变成可交互的动态页面 (用户可以点击按钮、滚动加载更多内容等)