Skip to content

Commit

Permalink
vault backup: 2024-10-21 16:11:30
Browse files Browse the repository at this point in the history
  • Loading branch information
sdasd22q committed Oct 21, 2024
1 parent 84a3db9 commit 515c46e
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 10 deletions.
21 changes: 11 additions & 10 deletions docs/blog/.obsidian/workspace.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
"state": {
"type": "markdown",
"state": {
"file": "frontend/node/node-log.md",
"file": "frontend/react/next-render-way.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
"title": "node-log"
"title": "next-render-way"
}
}
]
Expand Down Expand Up @@ -93,7 +93,7 @@
"state": {
"type": "backlink",
"state": {
"file": "frontend/node/node-log.md",
"file": "frontend/react/next-render-way.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
Expand All @@ -103,7 +103,7 @@
"unlinkedCollapsed": true
},
"icon": "links-coming-in",
"title": "node-log 的反向链接列表"
"title": "next-render-way 的反向链接列表"
}
},
{
Expand Down Expand Up @@ -139,13 +139,14 @@
"state": {
"type": "outline",
"state": {
"file": "frontend/node/node-log.md"
"file": "frontend/react/next-render-way.md"
},
"icon": "lucide-list",
"title": "node-log 的大纲"
"title": "next-render-way 的大纲"
}
}
]
],
"currentTab": 3
}
],
"direction": "horizontal",
Expand All @@ -163,8 +164,9 @@
},
"active": "4356ccb312dc0979",
"lastOpenFiles": [
"frontend/node/node-send-email.md",
"frontend/node/node-log.md",
"frontend/react/next-render-way.md",
"frontend/node/node-send-email.md",
"frontend/node/nest-core.md",
"frontend/node/oss-upload.md",
"frontend/node/file-upload.md",
Expand Down Expand Up @@ -193,7 +195,6 @@
"Pasted image 20240806223732.png",
"Pasted image 20240806223717.png",
"frontend/node/custom-cli.md",
"frontend/nest",
"internship/baidu.md"
"frontend/nest"
]
}
93 changes: 93 additions & 0 deletions docs/blog/frontend/react/next-render-way.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# nextjs 渲染

## 几种渲染方式

### CSR

**CSR,英文全称“Client-side Rendering”,中文翻译“客户端渲染”。顾名思义,渲染工作主要在客户端执行。**

像我们传统使用 React 的方式,就是客户端渲染。浏览器会先下载一个非常小的 HTML 文件和所需的 JavaScript 文件。在 JavaScript 中执行发送请求、获取数据、更新 DOM 和渲染页面等操作。

这样做最大的问题就是不够快。(SEO 问题是其次,现在的爬虫已经普遍能够支持 CSR 渲染的页面)

在下载、解析、执行 JavaScript以及请求数据没有返回前,页面不会完全呈现。

### SSR

**SSR,英文全称“Server-side Rendering”,中文翻译“服务端渲染”。顾名思义,渲染工作主要在服务端执行。**

比如打开一篇博客文章页面,没有必要每次都让客户端请求,万一客户端网速不好呢,那干脆由服务端直接请求接口、获取数据,然后渲染成静态的 HTML 文件返回给用户。

虽然同样是发送请求,但通常服务端的环境(网络环境、设备性能)要好于客户端,所以最终的渲染速度(首屏加载时间)也会更快。

虽然总体速度是更快的,但因为 CSR 响应时只用返回一个很小的 HTML,SSR 响应还要请求接口,渲染 HTML,所以其响应时间会更长,对应到性能指标 TTFB (Time To First Byte),SSR 更长。

### SSG

**SSG,英文全称“Static Site Generation”,中文翻译“静态站点生成”。**

SSG 会在构建阶段,就将页面编译为静态的 HTML 文件。

比如打开一篇博客文章页面,既然所有人看到的内容都是一样的,没有必要在用户请求页面的时候,服务端再请求接口。干脆先获取数据,提前编译成 HTML 文件,等用户访问的时候,直接返回 HTML 文件。这样速度会更快。再配上 CDN 缓存,速度就更快了。

所以能用 SSG 就用 SSG。“在用户访问之前是否能预渲染出来?”如果能,就用 SSG。

### ISR

**ISR,英文全称“Incremental Static Regeneration”,中文翻译“增量静态再生”。**

还是打开一篇博客文章页面,博客的主体内容也许是不变的,但像比如点赞、收藏这些数据总是在变化的吧。使用 SSG 编译成 HTML 文件后,这些数据就无法准确获取了,那你可能就退而求其次改为 SSR 或者 CSR 了。

考虑到这种情况,Next.js 提出了 ISR。当用户访问了这个页面,第一次依然是老的 HTML 内容,但是 Next.js 同时静态编译成新的 HTML 文件,当你第二次访问或者其他用户访问的时候,就会变成新的 HTML 内容了。

Next.js v9.5 就发布了稳定的 ISR 功能,这是当时提供的 [demo](https://link.juejin.cn/?target=https%3A%2F%2Freactions-demo.vercel.app%2F "https://reactions-demo.vercel.app/") 效果:

![reactions-demo.gif](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/26964dd0d6c14517abe5aa90fca2bba6~tplv-k3u1fbpfcp-jj-mark:2495:0:0:0:q75.awebp#?w=1434&h=1464&s=1406805&e=gif&f=226&b=fcfcfc)


## SSR 和 RSC

### React Server Component

React Server Component 把数据请求的部分放在服务端,由服务端直接给客户端返回带数据的组件。

最终的目标是:在原始只有 Client Components 的情况下,一个 React 树的结构如下:

![image.png](https://codertzm.oss-cn-chengdu.aliyuncs.com/20241021160734.png)

在使用 React Server Component 后,React 树会变成:

![image.png](https://codertzm.oss-cn-chengdu.aliyuncs.com/20241021160746.png)

其中黄色节点表示 React Server Component。在服务端,React 会将其渲染会一个包含基础 HTML 标签和 **客户端组件占位** 的树。它的结构类似于:

![image.png](https://codertzm.oss-cn-chengdu.aliyuncs.com/20241021160833.png)

因为客户端组件的数据和结构在客户端渲染的时候才知道,所以客户端组件此时在树中使用特殊的占位进行替代。

当然这个树不可能直接就发给客户端,React 会做序列化处理,客户端收到后会在客户端根据这个数据重构 React 树,然后用真正的客户端组件填充占位,渲染最终的结果。

![image.png](https://codertzm.oss-cn-chengdu.aliyuncs.com/20241021160855.png)


使用 React Server Component,因为服务端组件的代码不会打包到客户端代码中,它可以减小包(bundle)的大小。且在 React Server Component 中,可以直接访问后端资源。当然因为在服务端运行,对应也有一些限制,比如不能使用 useEffect 和客户端事件等。

了解了 RSC 和 SSR 这两个基本概念,现在让我们来回顾下。表面上看,RSC 和 SSR 非常相似,都发生在服务端,都涉及到渲染,目的都是更快的呈现内容。但实际上,这两个技术概念是相互独立的。RSC 和 SSR 既可以各自单独使用,又可以搭配在一起使用(搭配在一起使用的时候是互补的)。

正如它们的名字所表明的那样,Server-side Rendering 的重点在于 **Rendering**,React Server Components 的重点在于 **Components**

简单来说,RSC 提供了更细粒度的组件渲染方式,可以在组件中直接获取数据,而非像 Next.js v12 中的 SSR 顶层获取数据。RSC 在服务端进行渲染,组件依赖的代码不会打包到 bundle 中,而 SSR 需要将组件的所有依赖都打包到 bundle 中。

当然两者最大的区别是:

SSR 是在服务端将组件渲染成 HTML 发送给客户端,而 RSC 是将组件渲染成一种特殊的格式,我们称之为 RSC Payload。这个 RSC Payload 的渲染是在服务端,但不会一开始就返回给客户端,而是在客户端请求相关组件的时候才返回给客户端,RSC Payload 会包含组件渲染后的数据和样式,客户端收到 RSC Payload 后会重建 React 树,修改页面 DOM。


使用 SSR,需要经过一系列的步骤,用户才能查看页面、与之交互。具体这些步骤是:

1. 服务端获取所有数据
2. 服务端渲染 HTML
3. 将页面的 HTML、CSS、JavaScript 发送到客户端
4. 使用 HTML 和 CSS 生成不可交互的用户界面(non-interactive UI)
5. React 对用户界面进行水合(hydrate),使其可交互(interactive UI)

0 comments on commit 515c46e

Please sign in to comment.