页面呈现过程中的前端性能优化点

  1. 浏览器请求过程
    1. 1、cookie free
    2. 2、domain hash
    3. 3、css sprites
    4. 4、js/css combine
    5. 5、max expires time
    6. 6、loading images on demand
  2. 资源加载
  3. 浏览器渲染页面
    1. 渲染过程
    2. 重绘和重排
    3. 针对渲染的优化方法
  4. PageSpeed
  5. 最后

前端性能优化是使 页面 更快、更好、无错误、用户操作更流畅、体验更好。

从用户输入URL到页面整个呈现在用户眼前,还有用户交互的过程都是性能优化的切入点。

浏览器请求过程

当浏览器请求一个URL的时候,会经过以下过程:阻挡、域名解析、建立连接、发送请求、等待响应、接收数据。

阻挡:不同浏览器对于单个域名的最大并发连接数有一定的限制,如果浏览器同时对某个域名发起多个请求,超多限制就会出现等待,也就是阻挡。

以下和浏览器并发相关的性能优化技术 参阅知乎黄良懿的答案。

和并发资源数有关的性能优化技术:
domain hash, cookie free, css sprites, js/css combine, max expires time, loading images on demand

1、cookie free

启用和主站不同的域名来放置静态资源,减少不必要的cookie发送

按照普通设计,当网站cookie信息有1 KB、网站首页共150个资源时,用户在请求过程中需要发送150 KB的cookie信息,在512 Kbps的常见上行带宽下,需要长达3秒左右才能全部发送完毕。 尽管这个过程可以和页面下载不同资源的时间并发,但毕竟对速度造成了影响。 而且这些信息在js/css/images/flash等静态资源上,几乎是没有任何必要的。 解决方案是启用和主站不同的域名来放置静态资源,也就是cookie free。

2、domain hash

由于浏览器对于单个域名的并发数限制,可以使用多个域名加大浏览器并发量

将css放置在页面最上方应该是很自然的习惯,但第一个css内引入的图片下载是有可能堵塞后续的其他js的下载的。而在目前普遍过百的整页请求数的前提下,浏览器提供的仅仅数个并发,对于进行了良好优化甚至是前面有CDN的系统而言,是极大的性能瓶颈。 这也就衍生了domain hash技术来使用多个域名加大并发量(因为浏览器是基于domain的并发控制,而不是page),不过过多的散布会导致DNS解析上付出额外的代价,所以一般也是控制在2-4之间。 这里常见的一个性能小坑是没有机制去确保URL的哈希一致性(即同一个静态资源应该被哈希到同一个域名下),而导致资源被多次下载。

3、css sprites

通过使用css sprites减少请求总数。

再怎么提速,页面上过百的总资源数也仍然是很可观的,如果能将其中一些很多页面都用到的元素如常用元素如按钮、导航、Tab等的背景图,指示图标等等合并为一张大图,并利用css background的定位来使多个样式引用同一张图片,那也就可以大大的减少总请求数了,这就是css sprites的由来。

4、js/css combine

合并js、css文件减少浏览器的重新渲染
压缩资源减小传输的体积

全站的js/css原本并不多,其合并技术的产生却是有着和图片不同的考虑。 由于cs/js通常可能对dom布局甚至是内容造成影响,在浏览器解析上,不连贯的载入是会造成多次重新渲染的。因此,在网站变大需要保持模块化来提高可维护性的前提下,js/css combine也就自然衍生了,同时也是minify、compress等对内容进行多余空格、空行、注释的整理和压缩的技术出现的原因。

5、max expires time

静态资源缓存有效期加长

随着cookie free和domain hash的引入,网站整体的打开速度将会大大的上一个台阶。 这时我们通常看到的问题是大量的请求由于全站公有header/footer/nav等关系,其对应文件早已在本地缓存里存在了,但为了确保这个内容没有发生修改,浏览器还是需要请求一次服务器,拿到一个304 Not Modified才能放心。 一些比较大型的网站在建立了比较规范的发布制度后,会将大部分静态资源的有效期设置为最长,也就是Cache-Control max-age为10年。 这样设置后,浏览器就再也不会在有缓存的前提下去确认文件是否有修改了。 超长的有效期可以让用户在访问曾访问过的网站或网页时,获得最佳的体验。 带来的复杂性则体现在每次对静态资源进行更新时,必须发布为不同的URL来确保用户重新加载变动的资源。

6、loading images on demand

图片按需加载,用占位符填补图片空位,待图片进入可视区域再进行加载

即使是这样做完,仍然还存在着一个很大的优化空间,那就是很多页面浏览量很大,但其实用户直接很大比例直接就跳走了,第一屏以下的内容用户根本就不感兴趣。 对于超大流量的网站如淘宝、新浪等,这个问题尤其重要。 这个时候一般是通过将图片的src标签设置为一个loading或空白的样式,在用户翻页将图片放入可见区或即将放入可见区时再去载入。 不过这个优化其实和并发资源数的关系就比较小了,只是对一些散布不合理,或第一页底部的资源会有一定的帮助。 主要意图还是降低带宽费用。

资源加载

浏览器在加载html时,只要网络层返回一部分数据后就会开始解析,遇到外链样式、脚本、图片都会像服务器请求资源,而不需要等到所有html都下载完成才开始,渲染也是同步进行的。

1、将css放在html的头部可以随html的加载一起渲染页面,减少页面空白时间,更快的让用户看到渲染的页面。

2、js的下载和解析会阻塞其他的下载和呈现,所以尽量将js在页面底部。

JS 和 CSS 的位置对其他资源加载顺序的影响

3、延迟加载js文件。

4、按需加载资源。

浏览器渲染页面

渲染过程

浏览器渲染引擎的渲染过程,主要有三步骤:

1、解析。浏览器会解析HTML/SVG/XHTML,事实上,webkit有三个C++的类对应这三类文档。浏览器解析这三种文件会产生一个DOM Tree;解析CSS,产生style rules;解析Javacript,主要通过DOM API和CSSOM API来操作DOM Tree和CSS Rule Tree

2、浏览器引擎通过DOM Tree和CSS Rule Tree来构造Rendering Tree。
Rendering Tree 并不与 DOM Tree 对应,比如像 标签内容或带有 display: none; 的元素节点并不包括在 Rendering Tree 中 。
通过 CSS Rule Tree 匹配 DOM Tree 进行定位坐标和大小,是否换行,以及 position、overflow、z-index 等等属性,这个过程称为 Flow 或 Layout 。

3、最终通过调用Native GUI 的 API 绘制网页画面的过程称为 Paint。

重绘和重排

当用户在浏览网页时进行交互或通过 js 脚本改变页面结构时,以上的部分操作有可能重复运行,此过程称为 Repaint 或 Reflow。

Repaint
当元素改变的时候,将不会影响元素在页面当中的位置(比如 background-color, border-color, visibility),浏览器仅仅会应用新的样式重绘此元素,此过程称为 Repaint。

Reflow
当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为 Reflow。( HTML 使用的是 flow based layout ,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫 Reflow。)

Reflow 的成本比 Repaint 的成本高得多的多。一个结点的 Reflow 很有可能导致子结点,甚至父点以及同级结点的 Reflow 。在一些高性能的电脑上也许还没什么,但是如果 Reflow 发生在手机上,那么这个过程是延慢加载和耗电的。—-浏览器的渲染原理简介

  • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
  • 当你移动DOM的位置,或是搞个动画的时候。
  • 当你修改CSS样式的时候。
  • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
  • 当你修改网页的默认字体时。

针对渲染的优化方法

1、减少 CSS 嵌套层级和选择适当的选择器(CSS匹配DOM Tree主要是从右到左解析CSS的Selector)
2、不要通过 JS 逐条修改 DOM 的样式,提前定义好 CSS 的 Class 进行操作。
3、把DOM离线后修改样式。
4、不要把DOM结点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。
5、尽可能的为产生动画的 HTML 元素使用 fixed 或absolute 的 position ,那么修改他们的 CSS 是不会 Reflow 的。

PageSpeed

PageSpeed Insights是Google的一个网站性能测试工具,可以根据这十大规则来进行更多性能上的优化。

PageSpeed规则

最后

越来越重视用户体验的现在,性能优化也是前端比较重要的点,并且还有根据用户需求来做的优化,比如优先加载首屏、优先加载文章内容等… 在秒甚至毫秒级的时间里偷时间,这也是前端的乐趣所在。

最近正在读的性能优化的好书:
《Web性能实践日志》