本文以 React、Vue 为例,介绍下主流的渲染模式以及在主流框架中如何实现上述的渲染模式。

前置知识介绍

看渲染模式之前我们先看下几个主流框架所提供的相关能力,了解的可跳到下个章节。

挂载组件到 DOM 节点

这是主流框架最基本的能力,就是将组件渲染到指定的 DOM 节点上。在 React 中所使用的 API 是 render,在 Vue 中所使用的是 createApp 后的 mount。

水合

水合用来将组件渲染到已有的静态内容上,用于为静态页面恢复其交互和动态能力。在 React 中所使用的 API 是 hydrate(React 18 前的版本) 和 createHydrate(React 18),在 Vue 中所使用的是 createSSRApp 后的 mount。

Vue 中的 API 语义稍显奇怪,因为使用 createSSRApp 的场景并不一定是 SSR。

输出渲染内容

主流框架除了可以将组件渲染到 DOM 节点上以外,还能将其要渲染的内容直接输出为如 HTML 字符串等形式。输出为字符串的 API 在 React 和 Vue 中所使用的 API 都叫做 renderToString。

React 中还推出了很多其它的 API:如 renderToStaticMarkup、 renderToStaticNodeStream 等等。功能基本一致,不影响本文的内容所以此处不细说了。下面的例子中仅以 renderToString 为例。

主流渲染模式

知道了主流框架的这几种能力,我们再来通过标题提到的几种主流渲染模式看下他们能用来组合出什么样的效果,

CSR - Client Side Rendering - 客户端渲染

CSR 就是我们常见的 SPA 所使用的渲染方式,所有的主流框架都支持,或者说:只要是在客户端渲染过程中使用到了脚本都可以算作客户端渲染。

CSR 主要流程为:

  1. 浏览器加载页面
  2. 加载对应的脚本
  3. 脚本执行时向页面中渲染内容,此步骤一般包含两种方式:
    1. 向一个空节点中渲染内容,一般应用于纯粹的 CSR 应用。这里使用的就是上面提到的挂载组件的功能。
    2. 向一个已有内容的节点中渲染内容,通常应用于 CSR 与其它渲染模式(SSR、SSG、ISR)结合的场景下

CSR 的使用场景定义也很简单,如果在客户端页面有动态需求或需要交互则必须使用。

SSR - Server Side Rendering - 服务端渲染

SSR 是另一个比较常见的渲染模式,使用这种渲染模式可以从服务端直接返回要渲染的静态内容。

其常见流程为:

  1. 浏览器发起 HTTP 请求对应的页面
  2. 服务端接收到请求后准备渲染页面所需要的数据
  3. 将所需要的数据传入需要渲染的页面组件中然后通过 renderToString 输出为静态内容
  4. 拼接页面模版、水合脚本等将生成的静态内容返回到浏览器,浏览器进行渲染
  5. 浏览器渲染内容,执行水合脚本恢复页面交互和动态能力

纯粹的 SSR 指代的接收到请求、输出静态内容、返回浏览器的模式。水合的相关部分是属于 CSR 的内容。

要注意水合并不是必须的,可以按需选择。比如如果你的需求是要对不同的用户展示不同的页面,然而页面上并没有任何可以交互或动态的内容,那完全可以忽略水合的部分。

SSR 一般应用于以下场景:

  1. 出于首页打开速度、用户体验、SEO 等目的需要让用户更快的看到页面首屏内容
  2. 想要预先渲染的页面内容中存在动态的内容

SSG - Static Site Generation - 静态站点生成

SSG 现在也比较常见,它所指代的是在构建阶段就将页面所需要的数据准备好然后将需要的页面通过脚本构建为静态内容的模式。

其常见流程为:

  1. 在构建阶段构建脚本遍历所有需要静态构建的页面
  2. 获取渲染所需要的数据并通过 renderToString 输出为静态内容
  3. 将静态内容拼接页面模版和水合脚本等内容后保存到文件中
  4. 浏览器发起请求时从服务端返回静态页面(一般直接使用静态文件服务器即可)
  5. 浏览器渲染内容,执行水合脚本恢复页面交互和动态能力

纯粹的 SSG 指代的同样是不包含 CSR 部分的内容,即构建阶段生成静态页面并在请求时直接将静态页面返回的过程。水合过程同样不是必须的,视需求决定即可。

SSG 一般应用于以下场景:

  1. 出于首页打开速度、用户体验、SEO 等目的需要让用户更快的看到页面首屏内容
  2. 页面中基本都是静态内容,变动很少或变动的时机比较固定

所以常用于通过 CMS 生成内容、博客站点等静态内容较多的场景。

ISR - Incremental Static Regeneration - 增量静态再生

ISR 目前使用的不多,它算是 SSG 的一种增强版,指的是在 SSG 的基础上,服务端在收到页面请求时会对页面的时效性进行判断,如果认定失效则会对该页面进行增量构建的一种模式。

其常见的流程如下:

可以看出 ISR 在构建和客户端环节没有任何的变化,而是增加了 Server 端的逻辑:

  1. 在服务端收到对应页面请求时服务端会先返回当前内容然后对页面做失效验证
  2. 如果页面实现,服务端会对失效的页面进行后台增量构建
  3. 当下次请求到达时如果新的页面已经生成成功则会返回新页面的内容,但在此之前还会继续使用旧页面的内容

当然上述的逻辑并不绝对,先增量构建再返回也同样是 ISR,只是一般这样会影响到用户体验一般不推荐。

ISR 适用的场景是:

  1. 网站匹配 SSG 场景
  2. 但对页面有一定的实时性要求

比如说天气预报页面,可能半小时更新一次即可,或者是新闻页面,在存在新数据时再进行增量构建也是一种解决方案。

如何选择

在选择渲染模式时我们通过以下逻辑进行简单的判断:

  1. 客户端页面是否需要动态或交互能力,如果要则 CSR 为必选
  2. 如果页面有 SEO、首屏、性能等需求
    1. 如果页面中想要静态展示的内容对每次访问都可能存在差异——比如每个用户看到的页面信息不同,则可以选择 SSR
    2. 如果页面中静态展示的内容对每次访问没有差异性即可选择 SSG
      1. 如果页面中的静态内容变动较为频繁,则可选择 ISR

其次还要注意 SSR 和 ISR 都需要服务端的支持,所以如果只有静态文件服务器那需要的改动就比较大了。

最后

渲染模式其实远不止以上几种,很多场景下都可以进行相应的优化。以下是一些我能想到的场景:

  • 在录入或更新数据时通过 WebHook 等通知构建系统进行增量构建,算是 ISR 的一种变种
  • 在 SSR 场景下可以对静态组件和动态组件进行区分,将静态组件使用 SSG 输出,然后将其拼接到页面中。

所以没有最好的只有最适合的,按需选择最适合自己需求的渲染模式即可。

如果想要看 SSR、SSG、ISR 的具体实现请看我之前的文章。

什么是 CSR、SSR、SSG、ISR - 渲染模式详解的更多相关文章

  1. Extjs MVC开发模式详解

    Extjs MVC开发模式详解   在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开发模式, ...

  2. JavaScript严格模式详解

    转载自阮一峰的博客 Javascript 严格模式详解   作者: 阮一峰 一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict m ...

  3. HTTP协议头部与Keep-Alive模式详解

    HTTP协议头部与Keep-Alive模式详解 .什么是Keep-Alive模式? 我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器 ...

  4. (" use strict")Javascript 严格模式详解

    Javascript 严格模式详解 转载别人的博客内容,浏览了一遍,没有全部吸收,先保存一下链接 http://www.ruanyifeng.com/blog/2013/01/javascript_s ...

  5. Javascript设计模式之装饰者模式详解篇

    一.前言: 装饰者模式(Decorator Pattern):在不改变原类和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象. 装饰者模式的特点: 1. 在不改 ...

  6. HTTP协议Keep-Alive模式详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp22 HTTP协议Keep-Alive模式详解 1.什么是Keep-Aliv ...

  7. Java开源生鲜电商平台-盈利模式详解(源码可下载)

    Java开源生鲜电商平台-盈利模式详解(源码可下载) 该平台提供一个联合买家与卖家的一个平台.(类似淘宝购物,这里指的是食材的购买.) 平台有以下的盈利模式:(类似的平台有美菜网,食材网等) 1. 订 ...

  8. ext.js的mvc开发模式详解

    ext.js的mvc开发模式详解和环境配置 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开 ...

  9. Docker Kubernetes Service 网络服务代理模式详解

    Docker Kubernetes  Service 网络服务代理模式详解 Service service是实现kubernetes网络通信的一个服务 主要功能:负载均衡.网络规则分布到具体pod 注 ...

  10. ST MCU_GPIO的八种工作模式详解。

    补充: N.P型的区别,就是一个为正电压启动(NMOS),一个为负电压启动(PMOS) GPIO的八种工作模式详解 浮空输入_IN_FLOATING带上拉输入_IPU带下拉输入_IPD模拟输入_AIN ...

随机推荐

  1. [Linux]常用命令之【ulimit(资源限制)】

    0 常见问题 [WARN ] 2018-06-15 16:55:20,831 --New I/O server boss #1 ([id: 0x55007b59, /0.0.0.0:20880])-- ...

  2. 《花雕学AI》17:关注提示工程—本世纪最重要的技能可能就是与AI人工智能对话

    本文目录与主要结构 引言:介绍提示工程的概念和背景,说明为什么它是本世纪最重要的技能之一. 正文: 一.提示工程的基本原理和方法:介绍什么是提示.如何设计和优化提示.如何使用提示与语言模型进行交互. ...

  3. MySQL(十四)分析查询语句Explain 七千字总结

    分析查询语句:EXPLAIN 1概述 ​ 定位了查询慢的SQL之后,就可以使用EXPLAIN或者DESCRIBE工具做针对性的分析查询.两者使用方法相同,并且分析结果也是相同的. ​ MySQL中有专 ...

  4. count(*) count(1) count(字段)效率问题

    COUNT(字段名)和COUNT(*)的查询结果有什么不同? COUNT(1)和COUNT(*)之间的效率哪个更高? 你知道答案吗?很多人都认为COUNT(1)比COUNT(*)效率高,真的是这样吗? ...

  5. Node + Express 后台开发 —— 起步

    Node + Express 后台开发 -- 起步 前面陆续学习了一下 node.npm.模块,也稍尝试 Express,感觉得换一个思路加快进行. 比如笔者对前端的开发已较熟悉,如果领导给一个内部小 ...

  6. Cesium之Web Workers

    1. 引言 多线程是编程中常用的方法,例如,在桌面程序中,主线程一般是UI线程,负责UI绘制与用户交互,而运算处理往往是交给背后的工作线程,这样可以有效避免交互时的卡顿感 浏览器是多进程的,每打开一个 ...

  7. Golang defer使用

    学习于https://www.liwenzhou.com/posts/Go/function/的文章 1. defer的执行顺序类似于栈,"后进先出",也就是最先defer的语句最 ...

  8. 进程间通信WebSocket 服务端未启动时,客户端重连报错

    当WebSocket服务端未启动时,我们在客户端申请连接,会报 System.Net.Sockets.SocketException 异常. 当然,我们调试时异常设置默认是不勾选这个的.所以不影响正常 ...

  9. Python if 语句练习

    if语句 练习 # 1.以特殊方式跟管理员打招呼 # 创建一个至少包含 5 个用户名的列表,且其中一个用户名为 'admin' .想象你要编写代码,在每位用户登录网站后都打印一条问 # 候消息.遍历用 ...

  10. Python网页应用开发神器fac 0.2.6版本重要新功能一览

    fac项目地址:https://github.com/CNFeffery/feffery-antd-components ,欢迎star支持 大家好我是费老师,距离我的开源Python网页应用通用组件 ...