在pc的网页中,打开网站,能够迅速的给用户展现出来页面的东西,是非常重要的。而对于复杂的页面,如何让用户所关注的内容迅速的展现出来,这里大致有两种方式。 1、淘宝详情页采用的是BigRender 的方
在pc的网页中,打开网站,能够迅速的给用户展现出来页面的东西,是非常重要的。而对于复杂的页面,如何让用户所关注的内容迅速的展现出来,这里大致有两种方式。
1、淘宝详情页采用的是BigRender 的方式。这种的优化主要在浏览器端。我们都知道,当页面下载完毕后我们经过tokenizatoin-Tree Construction-Rendering。所以要让首屏的内容尽快的展现出来,我们需要给浏览器更少的工作量。这里往往有两种方式:
1):减少DOM节点数。节点数越少,浏览器的Rendering耗费的时间就更少。
2):减少脚本执行的时间。脚本执行和 UI Update 共享一个 thread, 脚本耗的时间越少,UI Update 就能越发提前
2、Facebook的BagPipe方式。先输出页面的整体布局,然后再输出脚本块,一边输出一遍渲染,将页面渲染回原来的布局中。这样可以让服务端的运算、网络传输和浏览器端的渲染变成并行。BigPipe 最主要解决的问题是服务端的运算时间,当服务端的运算时间大于 300 ~ 500ms 时才能体现出优势。当服务端响应非常快(小于 100ms),BigPipe 退化为上面讲的 BigRender.
减少DOM的节点数:
对于BigRender来说,减少DOM的节点数有两个方法。
- 和 Facebook 的 BigPipe 一样,调整页面代码为 页面布局 + 脚本块。BigPipe 是服务器 chunked 输出 html 内容,BigRender 是服务器一次性输出,其他都是一样的。
- 尽量少调整页面代码,但通过某种方式,将首屏不需要的 html 代码先存放起来。渲染好首屏后,再将存储好的 html 代码逐步渲染出来。
用JS存放HTML代码
facebook就是这么的一个做法
在<script> 标签中添加html代码,但是这种方法对于BigRender来说并不是特别的好
- 由于代码是存放在html中的字符串变量中的,所以对于单引号和双引号需要转义
- 由于 script 是内嵌的,需要对 script ETAGO 转义。
- 服务器端需要将 html 代码转化为一行。(也可以不转成一行,用续行符来做。)
- 当 html 代码中含有 script 时,需要先去除 script 中的单行注释,否则转化成一行时,会出问题
但是,这样做,当时优点也是非常大的:比如大幅度的减少了首屏渲染的时间。尽量不改变原有的开发习惯并且用非常少的代码完成了很大的优化。
用注释来存放代码
为了便于获取注释内容,添加一层包裹:
<div id="comment-data"><!--html code--></div>
用这种方式来获取内容
var htmlCode = document.getElementById(“comment-data”).childNodes[0].nodeValue;
但是缺点是:
- 服务端,html 中的
-->
要替换为某种特殊标记。(不能简单转义为-->
) - 服务端,html 中的
--
也要替换为某种特殊标记。否则在 Firefox 低版本中存在 bug. - 浏览器端,得到 htmlCode 后,要将上面的特殊标记替换回原值。
而且的那个注视里的东西太多的时候,这种方法的效率并不是忒高效。
用 textarea 来存放 html 代码
extarea 中的内容会按照 RCDATA 规则来解析:
- 遇到 & 时,会尽可能得到实体字符。
- 遇到 </textarea(/s|//|>) 时,会结束解析。
- 其他都直接作为 textarea 的内容。
<textarea id="area-data"><p>some text</p></textarea>
获取也是非常的简单:
var htmlCode = document.getElementById(“area-data”).value;
但是缺点就是:
- 服务端要讲html中的&转换成&
- 服务端要打破ETAGO
在时候我们再回到首屏渲染的问题上来说
可以根据实际情况,将页面划分成几大区域。非首屏区域,简单转义后,直接用 textarea 包裹起来。这样,DOM 数立刻就减少了。浏览器在拿到 html 代码时,首次 Tokenization — Tree Construction 的速度就会大大加快
完整的优化,还需要:
- 给浏览器合理的喘息(UI Update)时间,等首屏真正在显示器上绘制出来后,再进行下一步操作。
- 得到 textarea.value, 填充回 DOM 树时,得妥善处理内嵌的 script 代码。
- 对内嵌 script 代码中的 document.write 要妥善处理。
- 通过 textarea 回填,里面的非 defer 和 async 脚本会从同步变成异步。要妥善处理依赖关系,不破坏原有脚本逻辑。
- 对于优化项目来说,完备的测试和监控非常重要。
- 这次还做了 AssetsTransfer. 用户第一次访问时,会将首屏相关的脚本和样式内嵌,并做预加载。用户再次访问时,则改成外链方式,这样能充分利用浏览器缓存,并减少 html 传输量
当然!现在对于这种填充,angular都有了指令,我想h5也应该有所行动的,所以我觉得接下来应该研究下webComponents
的玩法了~