2242 字
11 分钟
SSR、SSG及 CSR 理解

序言#

对于做过前端工作而言,SSR(服务端渲染)、SSG(静态网站生成)及 CSR(客户端渲染) 三种渲染模式通常是逃不开的话题,然而对于很多后端临时(或被迫)加入前端的同学来讲,很可能就因此“误入歧途”,选择一款 时下非常流行的前端框架,而且大概率这款框架就是 Next.JS

而遍布项目全身的 use client ,更是会进一步折磨前端同事。所以,我觉得也有必要写一篇文章来仔细讨论一下前端的这些框架以及整个前端工程化的前世今生。

旧时代#

SSR 的诞生其实要早的多的多。 最早的互联网时代是只有静态网站的概念的,也就是几个网页就能撑起整个网站的时代。 但是这很难满足当时互联网日益膨胀的需求,所以,渐渐的有了一些动态网站的需求。自然而然的,也就诞生了一些诸如 PHP、ASP 这样的项目。 这些项目其实本身就是现在的 SSR 模式的雏形 —— 服务器渲染完整个 HTML。且用户拿到的仅仅是最后渲染完的 URL。

对于 JavaScript 还相对薄弱 (或说 V8 引擎还没发明)的时代来讲,这类渲染模式足以解决绝大多数应用场景。

但互联网的的发展是很快的,这种模式很快就带来了很多问题:

  • 所有代码混在在一块,十分难以维护,开发体验不高。
  • 每次请求都是一次全新请求,每次都是一次全加载,用户体验很差。
  • 服务器一直在计算各种各样的网页,对当时的服务器不太友好。

从某个角度上将,这个时代并不存在现在的前端概念:反而是在做全栈的人比较多。

CSR(客户端渲染时代)#

由于 Chrome V8 的大流行,大大加强了 JavaScript 的实力。同时,随着科技的发展,用户设备的性能也不再局限。

自然而然的,React 这样的框架就随之诞生了。

而到了现在,主流的 CSR 框架,包括 ReactVueAngular 等等。

与现在连教程都是 NextJS入门 的 React 不同,那时候的 React 更加着眼于用户的浏览器上。

一份典型的使用 CSR 的网页是如下结构1

index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

可以观察到的是,整个页面并没有任何包含页面样式或数据相关的内容,仅有一个id为 rootdiv节点信息。 这是因为,所有的一切,都包含在 JS 中了。

这样的有点比较明显:

  • 前端与后端的系统完全分离,后端完全在搞 API 即可。
  • 将前端彻底工程化,类似于整个网站就是就是一个完整的应用程序,可以很容易在里面实现各种的复杂页面与逻辑。

可以说,在 CSR 的世界中,浏览器就是个操作系统,需要实现的就是一整套完整的应用程序。

这样做的一个逻辑是:

  1. 浏览器先拿到一个空白的 HTML 文件和对应的 JS 文件链接。
  2. 请求 JS 文件然后执行。
  3. 根据 JS 的情况,渲染页面。
  4. 如果这个时候有数据请求,那么用户需要再次等待数据的返回。

可以看到,整个过程对于用户第一次打开其实是不太友好的。用专业的说法来讲,就是包括 FCP(First Contentful Paint)及 TTI(Time To Interact) 等这些带 First 或者 Time 的时间都比较长。

这也是为什么,CSR 的网页,在打开的时候,会经常性的白屏一段时间。

当然,为了解决减少一些这样的白屏,大家也搞出来了各种各样的手段,比如各种各样的懒加载,或者预加载。 但本质还是治标不治本。

此外,CSR 的网页,还有一个问题,就是对搜索引擎十分不友好。

由于 CSR, 内容实际上都是在 API 中返回的,搜索引擎无法再不执行 JS 的情况下获取到内容。

这对很多内容型网站,实际上是根本无法接受的 (当然,现在诸如 Goolge 这类搜索引擎,也加入一系列 CSR 的支持)。

当然, 这样的单页面也有很多好处::

  • 一些控制台类的程序,与 SEO 无关,反而程序全在本地执行,有了更加完美的体验。
  • 可以直接将网站部署在无需任何计算能力的 CDN 服务器上,整个前端基本不需要任何后端服务器的支持。

SSR(服务端渲染)#

尽管与旧时代都是服务端渲染,但现在所提到的 SSR 还是与旧时代有着一些明显的区别。相比较而言,现在的 SSR 更接近一种预渲染

其中比较明显的一点就是,就是整个页面逻辑仍然是与后端分开的。

当前 SSR 的一个逻辑是:

  1. Node.js 拿到用户的请求,确定用户访问的页面。
  2. 根据具体的请求,从数据库或者后端的 API 来获取数据。
  3. 根据内容,与模版整合,然后返回给用户。
  4. 浏览器拿到页面后,开始执行那些只能在客户端执行的部分。

对于开发人员来讲,与传统项目来讲,前端开发人员实际上还是沿用了 CSR 的开发模式 —— 数据无关的开发。

开发者仍然可以自己去实现页面的基本结构,而所有的内容仍然是从后端获取,只是这一步从浏览器端转移到了服务端。

这样做的好处显而易见:浏览器拿到的就是渲染好的页面

但是,这对于开发者的要求,要比 CSR 的开发高的多。

开发者需要提前分析整个页面的构造,然后决定什么东西是可以在服务端渲染的,而还有哪些内容是无法在服务端处理的。

滥用 use client 的写法,本质与 CSR 并无本质不同。
并且会让整个前端开发变得糟糕,难以维护的同时,
还增加了一台仅仅是用来提供 JS 文件的服务器增加了开销。

尽管服务器会尽快的提供一份渲染好的页面,浏览器端仍然会执行一些 JS 程序,而这个过程,我们会叫做 水合(hydration)

所谓的水合,也很好理解,就是客户端根据数据重新渲染页面,使其与服务端渲染一致。并绑定很多 JS 事件。

甚至部分称呼自己为混合渲染的框架,比如 Remix,更是会在水合之后,将页面转换为SPA 程序,实现同时 SSR 和 CSR 的效果。

对于很多内容形的网站,但是页面更新比较频繁,这种模式其实比较常见。

SSG(静态网站生成)#

服务端生成,顾名思义,就是服务端根据页面内容,在编译阶段,就生成静态的 HTML 文件。

使用 SSG 的网站,多是一些诸如本站这种博客类,或者是更新内容不频繁的内容型网站。

这些网站的主要特点在,可以在编译器就确定整个网站的结构与结构,而且对用户的交互需求实际上比较弱(一般也就个评论框)。

与 SSR 相比,SSG 则完全不依赖服务器,甚至可以部署在任何一台静态文件服务器上。

这种情况下,对服务器的要求就非常非常低,一台部署了 Nginx 的服务器就可以几乎无限的提供服务了。

这也是为什么诸如 Cloudflare,Vercel等大公司会免费提供这类服务的原因。

这类网站并不是完全舍弃了服务端交互的部分,而是将服务端交互的部分完全转移。

例如本站,就选择将服务端交互的部分(比如评论区),转移到了专门的服务,通过诸如脚本的方式来实现需要动态的功能。

这种模式下限制会比较多,也仅仅适用于一些不太影响页面主要内容的脚本。

结尾#

CSR、SSR以及 SSG 这三种渲染方案,更多额是要针对不同的应用场景进行选择,不能仅仅是哪个技术新就盲目的选择那个最受欢迎的框架。

注释#

  1. 代码来自 Github

SSR、SSG及 CSR 理解
https://23h.at/posts/ssrssg及-csr-理解/
作者
Hyprocritor
发布于
2024-11-16
许可协议
CC BY-NC-SA 4.0