Web 网页渲染的几种模式
本文主要内容来源于对上文的翻译,图也来源于此,加上了一点平时工作的理解,翻译不是很准确,有条件的可以直接阅读上文链接。本文主要是自己在阅读时做的笔记,供自己以后查看。
预备知识
几种常见的模式:
- SSR: Server-Side Rendering - rendering a client-side or universal app to HTML on the server.
- CSR: Client-Side Rendering - rendering an app in a browser, generally using the DOM.
- Rehydration: “booting up” JavaScript views on the client such that they reuse the server-rendered HTML’s DOM tree and data.
- Prerendering: running a client-side application at build time to capture its initial state as static HTML.
在开启渲染模式对比之前,了解几个有意义的性能对比参数:
- TTFB: Time to First Byte - seen as the time between clicking a link and the
first bit of content
coming in. - FP:
First Paint
- the first time any pixel gets becomes visible to the user. - FCP:
First Contentful Paint
- the time when requested content (article body, etc) becomes visible. - TTI:
Time To Interactive
- the time at which a page becomes interactive (events wired up, etc).
渲染模式
SSR 服务端渲染
Server-Side Rendering - 就是服务端渲染出 HTML 页面,比如以前的 JSP,PHP
除了 TTFB 会延长(服务端需要去准备相应的页面数据),其他三个性能参数都比较客观;
优点是更好的性能数据,客户端压力更小,利于 SEO;缺点是对服务端性能要求更高,压力较大;页面切换 无法渐进式加载
,每个页面都需要重新渲染,页面切换时不能定义过渡动画(间隔有白屏,Chrome 在同域名页面跳转时,有一个 PLS 优化 ,即延迟到下一个页面 FCP 节点时开始下一个页面的渲染);
在 2014 年以前,更多网站是以 SSR 的形式,随着前端职业化和 JS 技术的不断发展,纯 SSR 正在逐渐淡出历史舞台。
Static Rendering 静态页面渲染(古老的客户端渲染方式)
静态渲染就是直接用已经成型的 html 文件进行渲染,会有一些辅助的 JS 来增强页面交互;比如 Hexo 模板引擎生成的文章 Html,当然很多公司也还存在页面内容纯手工的做法,这种渲染适合交互少的一些官方展示性网站;
- 性能参数都比较优异,TTFB 和 FP 和 FCP 几乎相同;
- 适合 CDN 部署;
- 客户端与服务端压力都比较小;
静态渲染的缺点之一是必须为每个可能的 URL 生成单独的 HTML 文件。 当您无法提前预测这些 URL 的 URL 或具有大量唯一页面的网站时,这可能具有挑战性甚至不可行, 如果是纯手工开发,那开发效率相对也比较低。
但从工作几年的经验来看,这种纯静态渲染的网站除了一些文档,博客类网站,更多是借助 JS 技术来提高页面的可交互能力。
静态渲染与 SSR 渲染(或则服务端预渲染)很像,可以通过禁用 js 和 降低网速来甄别网站是采用的静态渲染技术还是预渲染技术;
CSR 客户端渲染
Client-side rendering (CSR) ,一种纯在客户端(浏览器)利用 JS 操作 Dom 渲染页面的方式. 所有的生成逻辑, 数据获取
, 模板
and 路由
都由浏览器而不是服务端来控制。
除了 TTFB 短,其他都会被延长,可以通过 Http2 的服务端推送与 <link rel=preload>
来提升 FCP;
客户端渲染
是当前最流行的渲染模式,常以 SPA 单页面应用
的方式存在;因为有 React,Vue, Angular 这种热门 UI 框架支持,加上 Webpack 的构建打包,开发效率相比前两种方式高出很多,页面可做很多复杂的交互操作与 图形渲染
;
由于 JS 和 CSS 的大小会影响首屏的渲染,所以最好做好代码分割,只提供页面渲染必要的资源代码,应用懒加载的形式来提供其余的资源时非常有必要的;
骨架屏渲染(CSR with Prerendering)在当代也是一种比较时髦的技术
,GatsBy 引擎就是这种技术的突出使用者。就是会先通过服务端渲染出一个大致的骨架,告诉用户网站已经对你的请求有响应了,但其实这个时候只能看到一个很模糊的布局且不能交互,得等到页面数据请求回来后,页面才开始正式的渲染。
Rehydration 同构渲染
同构其实就是 SSR+CSR 的合体
。首屏的 html 页面由服务端提供,然后加载 js,js 利用现有的 dom 树来接管渲染后页面的交互操作,跳转到新页面时就变成纯 CSR 渲染,是一种比较有技术含量的渲染方式,当下比较流行的 NextJs(React), NuxtJs(Vue)就是这种渲染技术的成熟框架;
从上图可看,TTFB,FP 和 SSR 几乎一样,FCP 会由于 js 的下载解析变长。页面看起来很快被渲染出来( 直出
),且看起可交互,但实际上这时候还不能马上响应时间,因为要等到客户端 JS 执行,事件监听启动后,输入这些交互操作才可用,所以 TTI 相比 SSR 也会变长。
优点:利于 SEO,同时结合了 SSR 与 CSR 的特点,首屏之后的页面交互可实现渐进式加载,可控性高;
缺点:
- 技术要求更高(包含代码处理),同时对服务器和客户端都有性能要求;
- React 过去提供的服务端 html 生成方法 renderToString 是同步的,这回阻塞 Node 服务主线程;但后面推出了异步的 renderToNodeStream,服务端压力相对而言就没那么大了
我自己在公司的两个项目做过同构尝试,都是基于 Dva 的 React 同构渲染项目,感兴趣的话,可作为参考入门。
对于同构渲染可以优化的点,自己的总结是:
- JS,CSS 等页面静态资源文件,最好还是单独部署走 CDN;
- 交互 JS 在页面交互要求不高的情况下,可以设置
async
或则deffer
标志
其他
没咋理解,想了解最好看原文
- Partial Rehydration 部分同构渲染:顾名思义就是页面的部分组件或试图采用渐进式同构的方式加载,主要目的是减少页面对客户端 JS 的依赖;
- Trisomorphic Rendering,三态渲染:这种渲染技术仅适用于 service workers 可用的时候,大致意思是,首先由服务端提供一个初始文件流,然后 service workers 接管将文件流渲染出一个 html 文件,并开始在页面渲染,同时服务端也在生成可用的页面;下图是其提供的思路:
贴出原文:
If service workers are an option for you, “trisomorphic” rendering may also be of interest. It's a technique where you can use streaming server rendering for initial/non-JS navigations, and then have your service worker take on rendering of HTML for navigations after it has been installed. This can keep cached components and templates up to date and enables SPA-style navigations for rendering new views in the same session. This approach works best when you can share the same templating and routing code between the server, client page, and service worker
总结
在决定渲染方法时,请思考并了解您应用的瓶颈在哪;考虑静态渲染还是服务器渲染是否可以帮助您达到 90%的效果;完全可以以最少的 JS 来配合 HTML 来获得交互体验也是完全可以的,下面是一个全文总结性的图表:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论