前端性能优化:当页面渲染遇上边缘计算

云计算 边缘计算
本文在 ESI (Edge Side Include) 的基础上,提出了一种新的优化思路:边缘流式渲染方案(ESR),即借助 CDN 的边缘计算能力,将静态内容与动态内容以流式的方式,先后返回给用户。

[[327793]]

当前几种常见的前端性能优化方案仍然不可避免地会存在一些缺点。本文在 ESI (Edge Side Include) 的基础上,提出了一种新的优化思路:边缘流式渲染方案(ESR),即借助 CDN 的边缘计算能力,将静态内容与动态内容以流式的方式,先后返回给用户。

背景

对于 web 页面来说,首跳场景(例如 SEO、付费引流)的性能普遍比二跳场景下要差。原因有多种,主要是首跳用户在连接复用,和本地资源缓存利用方面,有很大的劣势。首跳场景下,很多在端上的优化手段(预加载,预执行,预渲染等)无法实施。

在客户端缓存能力无法利用的情况下,利用 cdn 距离用户近的特性,可以结合缓存做一些性能优化。

思路

思路 1:SSR

为了性能优化考虑,我们一般都会通过服务端渲染(SSR) ,将首屏动态内容直接服务端输出。

 

这种方式的优点是一次 html 返回即可包含页面主体内容,不需要浏览器二次请求接口后再用 js 渲染。但这种方式的缺点也比较明显,对于距离服务端远,或者服务端处理时间较长的场景,用户会看到较长时间的白屏。而且即使 html 返回完成了,用户并不会立即看到内容,页面还需要加载前置的 js,css 等资源后,才能看到内容。

思路 2:CSR + CDN

为了减少白屏时间,考虑利用 CDN 的边缘缓存能力,可以把页面 html 直接缓存在 cdn 节点上。但对于大部分场景来说,页面的主体内容都是动态,或者个性化的,把全部 html 内容缓存在 cdn 上对于业务影响较大,很有少场景能接受。那么换个思路,只把 html 静态部分缓存在 cdn 上呢?其实这个思路也是一个很常见的操作,即把 html 的静态框架部分缓存在 cdn 上,让用户能快速看到部分内容,然后再在客户端发起异步请求,获取动态内容并且渲染(CSR)。CSR + CDN 模式下的渲染时序图如下:

 

这种方式的优点是页面静态框架缓存在 cdn 上,用户可以快速看到页面框架内容,减少白屏等待焦虑。缺点是完整的页面内容需要再执行 js ,拉取异步接口回来后再进行渲染。最终有意义的动态内容展示出来的时间,比 SSR 更晚。

思路 3:ESI

CSR + CDN 的方式,很好地解决了白屏时间问题,但带来了动态内容展示的延时。之所以有这个问题,是因为我们把页面的动态内容和静态内容分割到了两个阶段中,并且是串行的,而且串行过程中还穿插了 js 的下载和执行。有什么办法把动态内容和静态内容在 CDN 上整合起来呢?

ESI (Edge Side Include) 给了我们一个很好的思路启发,ESI 最初也是 CDN 服务商们提出的规范,可通过 html 标签里加特定的动态标签,可让页面的静态内容缓存在 cdn 上,动态内容可以自由组装。ESI 的渲染时序图如下:

 

这个方案看起来很美好,可以把静态的部分缓存在 CDN 上了,动态部分在用户请求时会动态请求和拼接。但最关键的问题在于,ESI 模式下,最终返回给用户的首字节,还是要等到所有动态内容在 CDN 上都获取和拼接完成。也就是并没有减少白屏时间,只是减少了 CDN 和服务器之间内容传输的体积,带来的性能优化收益很小。最终效果上与 SSR 区别不大。

虽然 ESI 的效果不符合我们预期,但给了我们很好的思考方向。如果能把 ESI 改造成可先返回静态内容,动态内容在 CDN 节点获取到之后,再返回给页面,就可以保证白屏时间短并且动态内容返回不推迟。如果要实现类似于流式 ESI 的效果,要求在 CDN 上能对请求进行细粒度的操作,以及流式的返回。CDN 节点上支持这么复杂的操作吗?答案是肯定的:边缘计算。我们可以在 CDN 上做类似于浏览器的 service worker 的操作,可对请求和响应做灵活的编程。

基于边缘计算的能力,我们有了一种新的选择:边缘流式渲染方案(ESR)。方案详情如下。

渲染流程

方案的核心思想是,借助边缘计算的能力,将静态内容与动态内容以流式的方式,先后返回给用户。cdn 节点相比于 server,距离用户更近,有着更短的网络延时。在 cdn 节点上,将可缓存的页面静态部分,先快速返回给用户,同时在 cdn 节点上发起动态部分内容请求,并将动态内容在静态部分的响应流后,继续返回给用户。最终页面渲染的时序图如下:

 

从上图可以看出,cdn 边缘节点可以很快地返回首字节和页面静态部分内容,然后动态内容由 cdn 发起向 server 起并流式返回给用户。方案有以下特点:

  • 首屏 ttfb 会很短,静态内容(例如页面 Header 、基本结构、骨骼图)可以很快看到。
  • 动态内容是由 cdn 发起,相比于传统浏览器渲染,发起时间更早,且不依赖浏览器上下载和执行 js。理论上,最终 reponse 完结时间,与直接访问服务器获取完整动态页面时间一致。
  • 在静态内容返回后,已经可以开始部分 html 的解析,以及 js, css 的下载和执行。把一些阻塞页面的操作提前进行,等完整动态内容流式返回后,可以更快地展示动态内容。
  • 边缘节点与服务端之间的网络,相比于客户端与服务端之间的网络,更有优化空间。例如通过动态加速,以及 edge 与 server 之间的连接复用,能为动态请求减少 tcp 建连和网络传输开销。以做到最终动态内容的返回时间,比 client 直接访问 server 更快。

demo 对比

目前在 alicdn 上对主搜页面做了一个 demo (https://edge-routine.m.alibaba.com/), 下面是在不同网络(通过 charles 的 network throttle 配置限速)情况下,与原始页面的加载对比:

不限速(wifi)

限速 4G

 

限速 3g

5ad68981e9017.jpg" target="_blank">5ad68981e9017.jpg" width="auto" border="0" height="auto" alt="" title="">

 

从上面结果可以看出,在网速越慢的情况下,通过 cdn 流式渲染的最终主要元素出来的时间比原始 ssr 的方式出来得越早。这与实际推论也符合,因为网络越慢,静态资源加载时间越慢,对应的浏览器提前加载静态资源带来的效果也越明显。另外,不管在什么网络情况下,cdn 流式渲染方式的白屏时间要短很多。

整体架构

架构图

5acfb3ed6f4e186a32433dbb.jpg" target="_blank">5acfb3ed6f4e186a32433dbb.jpg" width="auto" border="0" height="auto" alt="" title="">

 

边缘流式渲染

1 模板

模板就是一个类似于包含 ESI 区块的语法,基于模板,会将需要动态请求的内容提取出来,把可以静态返回的内容分离出来并缓存起来。所以模板本质上定义了页面动态内容和静态内容。

在流式渲染过程中,会从上到下解析页面模板,如果是静态内容,直接返回给用户,如果遇到动态内容,会执行动态内容的 fetch 逻辑。整个过程中可能有静态和动态内容交替出现。

设计有以下几种类型的模板。

1)原始 HTML

这种模板对现有业务的侵入性最小,只需要在现有的 SSR 页面内容里加上一定的标签,即可把页面中动态部分申明出来:

  1. <html> 
  2.   <head> 
  3.     <linkrel="stylesheet"type="text/css"href="index.css"
  4.     <scriptsrc="index.js"></script><metaname="esr-version"content="0.0.1"/> 
  5.   </head> 
  6.   <body> 
  7.     <div>staic content....</div> 
  8.     <scripttype="esr/snippet/start"esr-id="111"content="SLICE"></script> 
  9.     <div>dynamic content1....</div> 
  10.     <scripttype="esr/snippet/end"></script> 
  11.     <div>staic content....</div> 
  12.     <scripttype="esr/snippet/start"esr-id="222"content="https://test.alibaba.com/snippet/222"></script> 
  13.     <divid="222">         
  14.       dynamic content2.... 
  15.     </div> 
  16.     <scripttype="esr/snippet/end"></script> 
  17.   </body> 
  18. </html> 

 

 

责任编辑:武晓燕 来源: 阿里技术
相关推荐

2021-03-11 14:28:07

云计算云原生边缘计算

2022-04-27 10:35:27

边缘渲染前端

2023-04-10 11:18:38

前端性能优化

2017-04-25 16:20:10

页面优化滚动优化

2018-06-27 08:21:31

前端Web渲染

2012-02-16 10:04:07

数据中心云计算

2017-04-12 11:46:46

前端浏览器渲染机制

2020-01-14 15:54:20

边缘计算区块链

2022-02-24 16:15:16

OpenHarmon鸿蒙OpenEuler

2016-10-21 15:57:39

Rust编辑语言Fedora

2013-05-22 09:33:09

交互设计设计时间

2017-06-28 11:34:55

锐捷 医疗 物联网

2020-07-03 19:20:35

区块链云计算数字经济

2018-05-07 10:23:27

AI 云计算

2022-02-16 08:11:52

组件渲染前端

2016-12-08 10:57:08

渲染引擎前端优化

2015-09-16 13:54:30

Android性能优化渲染

2015-01-07 15:49:21

大数据SSD

2017-08-18 14:47:31

DDD微服务架构

2023-03-22 18:31:10

Android页面优化
点赞
收藏

51CTO技术栈公众号