phase 5 part 1: typescript, vue, react, ssr(Next.js 16) topics with lessons, scenarios, interviews, verified examples
This commit is contained in:
1 parent
7a32d2c9a6
commit
7b5cae7d24
39 files changed
+2482
-48
No files matched your search
@@ -0,0 +1,81 @@
|
||||
---
|
||||
id: frontend.ssr.rendering-modes
|
||||
title: 渲染模式:CSR / SSR / SSG / ISR、水合、流式渲染和 Nuxt 基础
|
||||
type: lesson
|
||||
domain: frontend
|
||||
stack: [ssr]
|
||||
tags: [CSR, SSR, SSG, ISR, 水合, Hydration, 流式渲染, Nuxt, SEO]
|
||||
level: intermediate
|
||||
prerequisites: [frontend.vue.reactivity-composition]
|
||||
est_hours: 2.5
|
||||
related: [frontend.ssr.nextjs-app-router, frontend.fe-testing-perf.index, frontend.ssr.interview]
|
||||
week: [7]
|
||||
order: 1
|
||||
---
|
||||
|
||||
# 渲染模式:CSR / SSR / SSG / ISR、水合、流式渲染和 Nuxt 基础
|
||||
|
||||
## 解释说明
|
||||
|
||||
| 模式 | 在哪里生成 HTML | 优点 | 缺点 | 适合 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| CSR(客户端渲染) | 浏览器执行 JS 后生成 | 服务器简单,交互流畅 | 首屏慢、SEO 差 | 后台系统、登录后的应用 |
|
||||
| SSR(服务端渲染) | 每次请求时服务器生成 | 首屏快、SEO 好、数据实时 | 服务器压力、需要 Node 服务 | 内容和数据经常变化的公开页面 |
|
||||
| SSG(静态生成) | 构建时生成 | 最快、可放 CDN | 数据更新要重新构建 | 文档、官网、博客 |
|
||||
| ISR(增量静态再生成) | 构建时生成 + 过期后后台重新生成 | 兼顾速度和更新 | 有短暂的旧数据 | 商品页、文章页 |
|
||||
|
||||
**水合(Hydration)**:服务端返回 HTML 后,浏览器加载 JS,把事件监听和状态“接”到已有的 DOM 上,页面才可以交互。问题:
|
||||
|
||||
- 水合不匹配:服务端和客户端渲染结果不一致(用了 `Date.now()`、`Math.random()`、`window`、本地时区),会报警告甚至重新渲染。
|
||||
- 首屏能看到但点不动(JS 还没加载完):通过减少客户端 JS、部分水合 / 服务端组件、懒加载缓解。
|
||||
|
||||
**流式渲染**:服务器先发送页面框架,慢的数据块准备好后再流式补上(React 的 Suspense、Next.js 的 `loading.tsx`),首字节更快。
|
||||
|
||||
**Nuxt**(Vue 的全栈框架,当前大版本 Nuxt 4,以官方文档为准:https://nuxt.com/docs):基于文件的路由、`useFetch` / `useAsyncData` 在服务端取数并把结果传给客户端避免重复请求、`server/` 目录写接口(Nitro 引擎)、按路由配置渲染模式(`routeRules`:SSR、预渲染、ISR 类缓存)。
|
||||
|
||||
## 案例
|
||||
|
||||
电商的帮助中心:常见问题页需要 SEO 和最快的首屏,用 SSG / ISR;智能客服对话需要登录和实时交互,是客户端组件;订单页登录后才能看,用 CSR 或 SSR 都可以,但要注意不能把用户数据缓存到 CDN。
|
||||
|
||||
## 代码示例
|
||||
|
||||
避免水合不匹配:只在客户端执行的逻辑放到挂载之后。
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
const now = ref<string | null>(null); // 服务端渲染时为 null,两端一致
|
||||
onMounted(() => {
|
||||
now.value = new Date().toLocaleString("zh-CN"); // 只在浏览器执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span>{{ now ?? "加载中" }}</span>
|
||||
</template>
|
||||
```
|
||||
|
||||
Nuxt 中服务端取数(结果会序列化到页面中,客户端水合时不会再请求一次):
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
const { data: faqs, error } = await useFetch("/api/faqs");
|
||||
</script>
|
||||
```
|
||||
|
||||
Next.js 的写法见下一课和 [examples/next-ai-chat](examples/next-ai-chat/)。
|
||||
|
||||
## 易错点
|
||||
|
||||
- 在服务端渲染阶段访问 `window`、`localStorage`。
|
||||
- 服务端渲染时使用了全局单例状态(Pinia、模块级变量),导致不同用户的数据串在一起:每个请求要创建新的实例。
|
||||
- 把带用户信息的 SSR 页面缓存到 CDN。
|
||||
- SSR 页面里调用很慢的接口,拖慢整个首屏:并行取数、流式渲染、超时降级。
|
||||
- 以为用了 SSR 就一定更快:服务器离用户远、取数慢时,TTFB 反而变差。
|
||||
|
||||
## 面试常问
|
||||
|
||||
- CSR、SSR、SSG、ISR 的区别和适用场景?
|
||||
- 什么是水合?水合不匹配的原因?
|
||||
- SSR 项目有哪些常见的坑?
|
||||
Reference in new issue
Block a user