「干货」你须要了解的六种渲染模式

背景

周末在网上冲浪, 看到个消息:NextJS 9.3 将静态站点生成功能引入了NextJS平台。html

静态站点生成, 也就是所谓的 SSG : Static Site Generationreact

喝了口水,顺便回忆了下如今的几种渲染模式:web

  1. SSR (Server Side Rendering)
  2. SSG (Static Site Generation)
  3. SSR With hydration
  4. CSR with Pre-rendering
  5. CSR (Client Side Rendering)
  6. Trisomorphic Rendering

都不是什么新鲜玩意, 就总结复习一下, 顺便分享给你们, 但愿能给各位带来一些启发。浏览器

正文

1. SSR (Server Side Rendering)

SSR, 服务端渲染。缓存

服务器呈现响应于导航为服务器上的页面生成完整的HTML。这样能够避免在客户端进行数据获取和模板化的其余往返过程,由于它是在浏览器得到响应以前进行处理的。服务器

服务器渲染一般会产生快速的 First Paint (FP)和 First Contentful Paint (FCP)。网络

在服务器上运行页面逻辑和呈现能够避免向客户端发送大量JavaScript,这有助于实现快速的交互时间 (TTI)。ide

这是有道理的,由于使用服务器渲染,实际上只是将文本和连接发送到用户的浏览器。工具

这种方法能够在很大范围的设备和网络条件下很好地工做,而且能够带来有趣的浏览器优化,例如流文档解析。post

该图显示了影响FCP和TTI的服务器渲染和JS执行

流程:

浏览器 --> 服务器 --> 服务器执行渲染 --> index.html(实时渲染的内容)) --> Render --> bundle.js + images --> Render

image-20191231111204363

优势

  • 内容当即可用 -由于将HTML发送给客户端,因此几乎会当即看到页面内容。
  • 无需获取其余客户端 -理想状况下,服务器呈现过程将进行全部必需的调用以获取数据,所以不会从客户端进行任何其余服务调用。
  • 很是适合SEO

缺点

  • 服务器上的速度较慢 -须要渲染两次页面:一次在服务器上,一次在客户端上。同事也可能正在从服务器进行服务调用以呈现页面,全部这些都须要时间,所以可能会延迟HTML向客户端的初始发送。
  • 与某些UI库不兼容 -若是你用的某些库使用了window,那你就要想办法来解决了。 由于 Node 中没有window 或者 document

2. SSG (Static Site Generation)

SSG:静态网站生成。

静态网站生成相似于服务器端渲染,不一样之处在于您在构建时而不是在请求时渲染页面。

与服务器渲染不一样,因为没必要动态生成页面的HTML,所以它还能够实现始终如一的快速到第一字节的时间。

一般,静态呈现意味着提早为每一个URL生成单独的HTML文件。

借助预先生成的HTML响应,能够将静态渲染器部署到多个CDN,以利用边缘缓存的优点。

该图显示了影响FCP和TTI的静态渲染和可选的JS执行

优势

  • 内容当即可用 -由于将HTML发送给客户端,因此几乎会当即看到页面内容。
  • 无需获取其余客户端 -理想状况下,服务器呈现过程将进行全部必需的调用以获取数据,所以不会从客户端进行任何其余服务调用。
  • 很是适合SEO
  • -静态内容的呈现速度速度很是快。
  • 没有服务器 -没必要运行服务器。

缺点

  • 大型站点可能会很慢 -若是路由不少,速度可能会变慢。
  • 与某些UI库不兼容 -若是你用的某些库使用了window,那你就要想办法来解决了。 由于 Node 中没有window 或者 document

3. SSR With hydration

hydration, 直译为水合

让人一脸懵逼。

简单点讲, 将功能放回到已经在服务器端中呈现的HTML中的整个过程,称为水合。

换句话说就是,对曾经渲染过的HTML进行从新渲染的过程称为水合。

此方法试图经过同时进行客户端渲染和服务器渲染,达到一种平衡。

导航请求(例如整页加载或从新加载)由服务器处理,该服务器将应用程序呈现为HTML,而后将JavaScript和用于呈现的数据嵌入到生成的文档中。

理想状态下,就能够像服务器渲染同样实现快速的First Contentful Paint,而后经过使用称为(re)hydration的技术在客户端上再次渲染来修补

这是一个新颖的解决方案,可是它也可能具备一些至关大的性能缺陷。

带水合的SSR的主要缺点是:

即便改进了First Paint,它也可能对可交互时间产生重大负面影响。

SSR的页面一般看起来具备欺骗性,而且具备交互性,可是在执行客户端JS并附加事件处理程序以前,实际上没法响应输入

在移动设备上可能要花费几秒钟甚至几分钟。

原理示意:

该图显示客户端渲染会对TTI产生负面影响

与JS致使的延迟互动相比,这个模型形成的问题可能会更加严重:

服务器响应导航请求返回了应用程序UI的数据描述。同时,但它还返回了用于组成该UI的源数据以及该UI的实现的完整脚本,该脚本随后在客户端启动。

仅在bundle.js完成加载和执行后,该UI才会变为可交互。

举个例子:

包含序列化UI,内联数据和bundle.js脚本的HTML文档

蓝色部分包含了初始的3个checkbox, 以及须要加载的bundle.js,

一开始, 你会当即看到UI, 等bundle加载并执行完成以后, 页面才会更新, 进入可交互状态。

从真实网站中收集的效果指标代表, 使用SSR水合模式效果并很差,强烈建议不要使用它。

缘由归结为用户体验:最终很容易使用户陷入怪异的山谷

4. CSR with Pre-rendering

Pre-render 原理是: 在构建阶段就将html页面渲染完毕,不会进行二次渲染。

也就是说,当初打包时页面是怎么样,那么预渲染就是什么样。

等到JS下载并完成执行,若是页面上有数据更新,那么页面会再次渲染。这时会形成一种数据延迟的错觉。

Pre-render 利用 Chrome 官方出品的 Puppeteer 工具,对页面进行爬取。

它提供了一系列的 API, 能够在无 UI 的状况下调用 Chrome 的功能, 适用于爬虫、自动化处理等各类场景。

它很强大,因此很简单就能将运行时的 HTML 打包到文件中。

原理是: 在 Webpack 构建阶段的最后,在本地启动一个 Puppeteer 的服务,访问配置了预渲染的路由,而后将 Puppeteer 中渲染的页面输出到 HTML 文件中,并创建路由对应的目录。

以此, 达到预渲染的目的。

流程:浏览器 --> 服务器 --> index.html(预渲染的内容) --> Render --> bundle.js + images --> Render

image-20191231113759430

5. CSR (Client Side Rendering)

CSR, 顾名思义, 客户端渲染。

客户端渲染,意味着: 直接使用JavaScript在浏览器中渲染页面

全部逻辑,数据获取,模板和路由均在客户端而不是服务器上处理

CSR 示意图:

该图显示了影响FCP和TTI的客户端渲染

流程:浏览器 --> 服务器 --> index.html(白屏) --> bundle.js --> images --> Render

image-20191231113956671

优势

  • 在服务器上快速 -由于仅呈现空白页,因此呈现速度很是快。
  • 支持静态 -空白页能够经过S3之类的服务静态生成和提供,从而使速度更快。
  • 支持单页应用程序 -客户端渲染是惟一支持单页应用程序或SPA的模型。
  • 成本相对较低 - CSR 相对于SSR/SSG, 更容易开发/维护。

缺点

  • 没有初始渲染 -若是应用很大,或者客户的链接速度很慢,加载时间过长,用户体验就不太好。

6. 三态渲染

若是你能够结合Service-Worker, 则三态渲染模式也可能派上用场。

在三态渲染模型中,可使用服务器流式渲染进行初始导航,而后让service worker 在 html加载完成后,继续进行导航html的渲染。

这样可使缓存的组件和模板保持最新状态,并启用SPA样式的导航,以在同一会话中呈现新视图。

若是能够在服务器,客户端页面和service worker之间共享相同的模板和路由代码时,这种方法十分有效。

三态渲染模型:

三态渲染图,显示浏览器和服务程序与服务器进行通讯

7. 服务端渲染 VS 客户端渲染

服务器渲染会为每一个URL按需生成HTML,比仅提供静态渲染内容要慢。

同时,也有一些优化空间: 服务器渲染+ HTML缓存能够大大减小服务器渲染时间。

服务器渲染的优点在于:与静态渲染相比,它可以提取更多"实时"数据并响应更完整的请求集。

总结

从 SSR -> CSR, 以及中间不一样的渲染模式, 都在图里:

该图显示了本文介绍的各类选择

本文中介绍的6种渲染模式,至于如何选择, 这里也给出一些不成熟的建议:

  1. 对seo要求不高,同时对操做需求比较多的项目,好比一些管理后台系统,建议使用 CSR。由于只有在执行完bundle以后, 页面才能交互,单纯能看到元素, 却不能交互, 意义不大, 并且SSR 会带来额外的开发和维护成本。
  2. 若是页面无数据,或者是纯静态页面,建议使用pre-render。 由于这是一种经过预览打包的方式构建页面,也不会增长服务器负担。
  3. 对seo和加载速度有比较大需求的,同时页面数据请求多的状况,建议使用 SSR

结尾

好了,天都黑了,大概就是这么多。

才疏学浅, 若有错误, 欢迎留言指正。

周末在研究 Reciol.js, 以为挺有意思, 后面大概会出一篇分析的文章, 敬请期待哦。

参考资料

相关文章
相关标签/搜索