带你深入理解 CSR,SSR,SSG 等常用渲染模式

前言

近期的工作涉及到了CSR, SSR, SSG,这篇文章旨在总结和归纳这些渲染模式。

SPAMPASSRCSR 这几个词可能在你的工作生涯中经常出现,网上相关文章也很多。如果你对这些概念感到模糊或完全不了解,希望本文能帮助你理解这些渲染模式。

SPA 与 MPA

MPA

MPA(multiple page application) 称为多页应用, 指的是有多个页面的应用,从技术手段上来讲,你可以这么粗略地理解。

  • 首屏速度快:各个页面相互独立,需要单独维护多个 html 页面,每个请求都直接返回 html。
  • 切换页面比较慢:基于原生浏览器的文档跳转(navigating across documents)。因此每一次的页面更新都是一次页面重载,这将带来巨大的重启性能消耗。
  • 对 SEO 友好:页面在初始时,就具有全部的页面内容而非 「无状态」,从而达到更好的收录效果。

SPA

SPA(single page application)称为单页应用。通过 js 去感知到 url 的变化,动态的将当前页面的内容清除掉,然后将下一个页面的内容挂载到当前页面上。此时的路由不是后端来做了,而是前端来做,动态显示需要的组件。

  • 页面切换速度快:路由跳转是基于特定的实现(如 vue-router,react-router 等前端路由),而非原生浏览器的文档跳转,避免了不必要的整个页面重载。
  • 前后端分离:基于前端路由,SPA 与应用后端解耦,使得前端不再依赖于后端的路由分配。
  • 首屏时间慢:首屏除了 html 还要额外请求并执行 js 文件,通过 js 在空页面上渲染首屏。
  • SEO 不友好:内容都是靠 js 渲染生成出来的,但搜索引擎并不识别这部分内容,导致 SEO 效果差

CSR(Client Side Rendering)

CSR(客户端渲染)是一种在浏览器上执行 JavaScript 以生成 DOM 并显示内容的渲染方法。CSR 更贴近现代前端开发,我们通常使用的 Vue 和 React 默认使用 CSR。其大致流程如下:

  1. 浏览器向前端服务器请求 html 和 js
  2. html 页面为空,初始加载不显示任何内容,通过执行 js 渲染内容
  3. 通过后端暴露的 API 进行交互

对于典型的 CSR 应用程序,浏览器仅接收一个用作应用程序容器的 HTML 页面,因此也称为单页应用,所以 CSR 的特点与之前提到的 SPA 类似。

image (2).png

SSR(Server Side Rendering)

概念

在早期,开发者喜欢使用 JSP 或其他模板渲染引擎来构建应用,这种方法被称为SSR(服务器端渲染)。与客户端渲染不同,SSR 输出的是渲染完整的 HTML,整个渲染过程在服务器端进行。

用户发起请求后,SSR 的流程大致如下:

  1. 后端服务通过数据层进行查询用户所需内容
  2. 处理业务逻辑
  3. 使用模板拼接页面
  4. 将渲染好的 HTML 字符串返回给客户端
  5. 前端渲染并加载 JS 脚本完成剩余交互

image (3).png

早期的 SSR 在内容更新/跳转,都需要再次请求服务器,重新加载一次页面。但在 React, Vue 等框架的加持下,我们语境中的 SSR 一般指的是首屏服务端渲染同构渲染(Isomorphic render),即新开页面访问 SSR 应用时,首屏会返回完整的 html,浏览器通过注水hydrate)成为 React 或 Vue 应用,后续用户进行跳转等操作时不会再向服务端请求 html,而是以类似单页应用的方式进行。

ssr1 (1).png

同构直出

上文中,我们提到了hydrate这个词,正是通过该操作使静态 html 页面转换成一个 Vue 或 React 应用,这依赖于 React 和 Vue 提供的「同构直出」功能。

在服务端渲染中,有两种页面渲染的方式:

  • 后端服务器获取数据并生成 HTML 返回给浏览器解析渲染页面
  • 浏览器在交互过程中,请求新的数据并动态更新渲染页面

这两种渲染方式的不同点在于运行环境的不同。同一份代码可以在客户端和服务器端运行,两个环境的渲染结果应该保持一致。因此,我们需要实现客户端和服务器端的路由、页面模板和数据共享。

image (4).png

我们通过webpack将打包出两份代码,一份在服务端运行。

vue服务端渲染构建 (1).png

整体流程

以 Nuxt 为例,整体的渲染流程如下所示:

SSR (1).png

两个重要的概念

脱水(dehydrate)

将组件树序列化成静态的 HTML 片段,能直接看到初始视图,不过已经无法与之交互了,但这种便携的形态尤其适合网络传输。这个脱去动态数据,成为风干标本一样的静态快照的过程被称为脱水(dehydrate)。

注水(hydrate)

与脱水相反,将这个 html 躯干复活为 Vue 应用的过程称为注水。客户端并不重新生成 HTML 组件,而是重用服务器发送给它的 HTML,并附加「数据」与「交互性」,构建成完整的 Vue 应用,这个过程被称为注水(hydrate)。

Hydration is a process where a frontend framework like React, VueJS re-uses the static HTML structure it receives from the server (that was created at server-side at build time), and instead of re-generating the HTML nodes on the browser, simply “breathes” event handlers and interactivity into it.

SSR 与 CSR 的对比

优点
  • SEO 友好:搜索引擎爬虫可以直接抓取到最终页面内容。而 CSR 直接返回的 html 为空壳,对一些不加载执行 js 的低级爬虫来说这个页面的内容就是空的。
  • 首屏时间更短:服务端渲染直接返回带有数据的 HTML 文本,浏览器只需解析 HTML 并构建 DOM 树,无需额外执行 JS 来渲染首屏元素。
缺点
  • 占用服务器资源:渲染工作从浏览器转移到服务器,新增了数据获取的 IO 和渲染 HTML 的 CPU 占用。
  • 代码复杂度增加:需要同时兼容客户端和服务器端,代码编写时需要考虑两端的执行环境,且某些依赖库只能在客户端运行,增加了编码的复杂性。

SSG(Static Site Generation)

概念

SSG(静态站点生成)与 SSR 的原理非常类似,但不同之处在于 HTML 文件是预先生成的,而不是在服务器实时生成。

工作流程

  1. 构建阶段:在构建过程中,SSG 将源文件和模板(如HTML、CSS)结合,生成静态页面。这些页面通常由预定义的布局、组件和样式组成。
  2. 预渲染:SSG 在构建过程中会自动执行预渲染。这意味着 SSG 会根据预定义的路由和数据源,在构建时生成静态页面的多个实例。例如,对于一个博客,每篇文章都可以在构建过程中生成一个独立的静态页面。
  3. 静态输出:一旦构建完成,SSG 将生成的静态页面输出到目标文件夹中。这些页面包含所有必要的 HTML、CSS 和 JavaScript,以及任何相关的静态资源(如图像、视频等)。
  4. 部署:生成的静态页面可以直接部署到任何支持静态文件的Web服务器上。因为这些页面不需要动态生成,所以它们可以被高效地缓存和交付给访问者,提供更好的性能和可扩展性。
  5. 用户访问:首屏直接解析 html 生成 dom。接着和 SSR 一样通过 hydrate 将整个应用转变成为 React 或 Vue 应用,使用户在交互时与单页应用无异。

ssg图示 (1).jpeg

特点

SSG 的优缺点都非常明显,通常适用于静态页面,例如文档、博客、帮助站点和电子商务产品。

优点
  • 性能高:相比 SSR 减轻了服务器压力,还可以将生成的静态资源放到 CDN 上,充分利用缓存。
  • SEO 友好:搜索引擎爬虫可以直接抓取到最终页面内容
  • 易于部署:生成的静态页面可以直接部署到任何支持静态文件的 Web 服务器上,无需依赖 Node 环境等。
  • 高度安全性:由于服务器不需要运行程序,因此服务器漏洞仅限于操作系统本身,维护也更加方便。
缺点
  • 静态:只适用于静态数据,对于经常改动的数据,需要每次重新生成页面。

ISR(Incremental Static Regeneration)

概念

ISR(增量式网站渲染)结合了 SSG 和 SSR 的优势。ISR 的核心思想是将部分静态页面在构建时生成,并在用户访问时进行增量更新。

在 ISR 中,静态页面的构建仍然是在构建时完成的,类似于 SSG。然而,与完全静态的 SSG 不同,ISR 允许某些页面在构建后仍保持动态,并在用户首次访问时进行渲染。一旦渲染完成,生成的静态页面被缓存,并在后续的请求中被直接提供,以提高性能和响应速度。

工作流程

  1. 构建阶段:在构建过程中,使用SSG(静态站点生成器)生成静态页面,并将这些页面上传到 CDN。
  2. 用户发起页面请求:

ISR (1).png

特点

优点

ISR 的优势在于它在静态和动态之间找到了一个平衡点。对于不经常变动的内容,可以通过SSG生成完全静态的页面,从而实现快速加载和低服务器负载。而对于可能需要频繁更新的部分,如评论区或实时数据,ISR 可以使用 SSR 来动态生成这些内容,并在后续的请求中进行增量更新,从而保持页面的实时性。

缺点
  • 访问到没被预渲染过的次要内容触发 fallback,需要进行 CSR,加载较慢。
  • 访问到之前被预渲染过,但已经过期且未更新的页面,会得到过期的缓存响应。用户刷新一次,才能看到新的数据。

应用场景

本质上来说,ISR 仍然是 SSG 的范畴,复杂场景仍然无法应对。其典型应用场景包括博客评论、最新文章列表等。通过将这些动态内容与静态页面结合使用,可以在保持高性能和安全性的同时,提供更丰富和实时的用户体验。


原文链接: https://juejin.cn/post/7233699680490799162/
推荐阅读
相关专栏
前端与跨平台
90 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。