1.浏览器渲染原理解析

想要提高网页的性能,首要的便是要理解浏览器渲染原理,下面关于浏览器的原理解析,我们以chrome内核webkit为例,其他内核的浏览器原理也基本大同小异,可触类旁通。

如上图所示,浏览器解析页面步骤可分为:

* 解析HTML(HTML Parser)

* 构建DOM树(DOM Tree)

* 构建CSSOM树(Style)

* 构建渲染树(Render Tree)

* 页面布局(Layout)

* 绘制渲染树(Painting)

这一过程可在chrome开发者工具的时间线中观察:

这里我们简要说一下以下四个概念:

* 布局(layout)

布局也称为重排或回流,布局流程输出的是一个“盒模型”,它会精确地捕获每个元素在视口内的精确位置和尺寸,HTML就是采用基于流的布局模型,页面元素的变动往往可能导致回流的发生,而回流的频发发生亦是影响页面性能的重要因素,另外,处于流后置位通常不会影响前置位的几何特征,故对后置位的修改往往比对前置位的修改对页面整体的影响要低。

* 绘制(paint)

绘制即是对DOM所分割的层(layer)进行对应的绘制,页面的回流一般都会伴随着重绘,但重绘行为的出现不一定伴随回流。

* 渲染层

层(layer)的概念对于有设计基础的人来说应该不陌生,我们平面直观所见到的图像是基于空间图层的重叠得到的,一般来说,拥有相同坐标空间的节点属于同一个渲染层。渲染层最初是用来实现层叠上下文,以此来保证页面元素以正确的顺序合成(composite),实现半透明重叠等效果。

创建渲染层的条件:

  * 根元素(HTML)

  * 有明确的position属性(relative,fixed,sticky,absolute)

  * 透明的(opacity小于1)

  * 有css滤镜(filter)

  * 有css mask 属性

  * 当前有对于 opacity,transform,fliter,backdrop-filter 应用动画

  * overflow属性不为visible

  * 等等......

* 合成层

合成层是特殊的渲染层,每个合成层有单独的绘图层,绘图层中的绘图上下文负责输出该层的位图,位图储存在共享内存中,作为纹理上传到GPU,最后由GPU将多个位图进行合成,最后绘制到屏幕上,而相对于合成层,一般的渲染层是和其第一个拥有绘图层的父层共用一个的绘图层的,提升为合成层后当需要repaint或reflow本身,不影响其它层,另外,合成层的位图会直接交由GPU合成处理,效率比CPU高。

渲染层提升为合成层的触发原因:

  * 直接原因

    * iframe video canvas flash 元素 有 3D transform

    * backface-visibility 为 hidden

    * 对 opacity、transform、fliter、backdropfilter 应用了 animation 或 transition

    * will-change(设置为 opacity、transform、top、left、bottom、right(其中 top、left 等需要设置明确的定位属性,如 relative 等))

  * 后代原因

    * 有合成层后代同时本身有 transform、opactiy(小于 1)、mask、fliter、reflection 属性

    * 有合成层后代同时本身 overflow 不为 visible

    * 有合成层后代同时本身 fixed 定位

    * 有 3D transform 的合成层后代同时本身有 preserves-3d 属性

    * 有 3D transform 的合成层后代同时本身有 perspective 属性

  * 重叠原因

    * 元素的 border box(content + padding + border) 和合成层的有重叠,margin 的重叠无效

    * 动画运行期间,元素可能和其他元素有重叠

2.影响页面性能的操作及优化分析

* 频繁操作DOM元素

使用js脚本频繁地操作DOM元素是影响页面性能的一大因素,频繁地对DOM进行操作可能导致页面重绘和回流的频繁发生,从而导致页面卡顿和性能消耗问题,从细节上可按如下方法进行优化:

1)使用文档片段

var fragment = document.createDocumentFragment();

//一些基于fragment的大量DOM操作
...... document.getElementById('myElement').appendChild(fragment);

2)设置DOM元素的display样式为none再操作该元素

var myElement = document.getElementById('myElement');
myElement.style.display = 'none'; //一些基于myElement的大量DOM操作
...... myElement.style.display = 'block';

3)复制DOM元素到内存中再对其进行操作

var old = document.getElementById('myElement');
var clone = old.cloneNode(true); //一些基于clone的大量操作
...... old.parentNode.replaceChild(clone, old);

4)用局部变量缓存样式信息从而避免频繁获取DOM数据

//bad operation

for (var i = 0; i < paragraphs.length; i++){
paragraphs[i].style.width = box.offsetWidth + 'px';
} //better operation var width = box.offsetWidth;
for (var i = 0; i < paragraphs.length; i++){
paragraphs[i].style.width = width + 'px';
}

5)合并多次DOM操作

//bad operation

var left = 10, top = 10;
el.style.top = top;
el.style.left = left; //better operation el.style.cssText += "; left: " + left + "px; top: " + top + "px;"; //better operation(将样式内容设置于某一类名,再进行元素类名绑定) el.className += " theclassName";

*css动画造成页面不流畅问题分析优化

使用css3动画造成页面的不流畅和卡顿问题,其潜在原因往往还是页面的回流和重绘,减少页面动画元素对其他元素的影响是提高性能的根本方向,而实现可如下:

1)设置动画元素position样式为absolute或fixed,可避免动画的进行对页面其它元素造成影响,导致其重排和重绘的发生;

2)避免使用margin,top,left,width,height等属性执行动画,用transform进行替代;

//bad operation

div {
height: 100px;
transition: height 1s linear;
} div:hover {
height: 200px;
} //better operation div {
transform: scale(0.5);
transition: transform 1s linear;
} div:hover {
transform: scale(1.0);
}

总而言之,尽量用transform和opacity完成动画的展示,因为这两个属性可以避免重排和重绘的发生。

页面渲染的流水线其实可简单表示为以下步骤,从性能方面考虑,应该尽量避开layout和paint两个步骤,只触发composite步骤,但目前能做到这一效果的只有transform和opacity两个属性,另外需要注意的是:只有元素提升为合成层的时候transform和opacity才不会触发paint,否则依旧触发。

3)合理的提升合成层,以减少页面不必要的绘制和重排

合成层的好处是不会影响到其他元素的绘制和不被其他层所影响,因此,为了彼此之前的影响造成的性能损失,我们需合理的将动画效果中的元素或固定元素提升为合成层。

提升合成层的最好方式是使用 CSS 的 will-change 属性。将will-change 设置为 opacity、transform、top、left、bottom、right 可以将元素提升为合成层。

#target {
will-change: transform;
}

will-target的兼容性如下:

对于还不兼容该属性的浏览器,我们使用3D transform予以代替

#target {
transform: translateZ(0);
}

对于像页面顶部栏,侧栏等固定不变的位置元素,我们也可将其提升为合成层以避免其被其他元素影响而发生重绘,但要注意,合成层的提升也意味着性能的消耗增加,我们必须通过调试以测出合理的临界值,不能盲目提升合成层,此外,盲目提升合成层也可能造成重叠产生的额外合成层,容易导致层爆炸的出现,即页面连锁出现大量合成层默认提升,建议用google的timeline进行监控调试,避免出现不必要的意外消耗。

如何提高web页面的性能的更多相关文章

  1. QQ音乐Android客户端Web页面通用性能优化实践

    QQ音乐 Android 客户端的 Web 页面日均 PV 达到千万量级,然而页面的打开耗时与 Native 页面相距甚远,需要系统性优化.本文将介绍 QQ 音乐 Android 客户端在进行 Web ...

  2. CSS垂直翻转/水平翻转提高web页面资源重用性——张鑫旭

    一.CSS下兼容性的元素水平/垂直翻转实现 随着现代浏览器对CSS3的支持愈发完善,对于实现各个浏览器兼容的元素的水平翻转或是垂直翻转效果也就成为了可能.相关的CSS代码如下: /*水平翻转*/ .f ...

  3. 提高Web页面性能的技巧

    现在动辄几兆大小的页面加载量,让性能优化成了不可避免的热门话题.WEB 应用越流畅,用户体验就会越好,继而带来更多的访问量.这也就是说,我们应该反省一下那些过度美化的 CSS3 动画和多重操作的 DO ...

  4. 前端开发,页面加载速度性能优化,如何提高web页面加载速度

    一个网页访问速度的快慢,  不仅看它服务器的配置,这里除去你空间主机配置很烂的情况以外,我们从网站开发方面来探讨,前端技术需要从哪些方面提高访问的速度,需要用到哪些技术手段. 文件的加载 图标的加载: ...

  5. ASP.NE的缓存技术提高Web站点的性能

    一:我们为什么要使用缓存? 先来理解一下asp.net缓存技术的基本原理:把访问频繁的数据以及需要花大量的时间来加载的数据缓存在内存中,那么用户在下次请求同样的数据时,直接将内存中的数据返回给用户,从 ...

  6. ASP.NET Core如何使用压缩中间件提高Web应用程序性能

    前言 压缩可以大大的降低我们Web服务器的响应速度,压缩从而提高我们网页的加载速度,以及节省一定的带宽. 何时使用相应压缩中间件 在IIS,Apache,Nginx中使用基于服务端的响应压缩技术.中间 ...

  7. CSS垂直翻转/水平翻转提高web页面资源重用性

                    /*水平翻转*/ .flipx {     -moz-transform:scaleX(-1);     -webkit-transform:scaleX(-1);   ...

  8. 掌握提高 Web 应用的性能的方法 之 优化 PHP 和 Laravel

    Laravel 有很多东西.但是快不是其中之一.让我们学习一些优化技巧,以加快运行速度! 自从 Laravel 诞生以来,没有一个 PHP 开发人员不受她的影响.他们是喜欢 Laravel 提供的快速 ...

  9. 提高 DHTML 页面性能

    联盟电脑摘要:本文说明了某些DHTML功能对性能的重大影响,并提供了一些提高DHTML页面性能的技巧. 目录 简介 成批处理DHTML更改 使用innerText 使用DOM添加单个元素 扩展SELE ...

随机推荐

  1. 《DSP using MATLAB》示例Example 8.14

    %% ------------------------------------------------------------------------ %% Output Info about thi ...

  2. BW数据加载

    BW数据加载的优先级   1.主数据属性的加载 步骤图  从下到上 1)运行InfoPackage加载到PSA 找到主数据属性的InfoPackage,双击  点击Start按钮  点击监视器,查看运 ...

  3. uGUI知识点剖析之AutoLayout

    http://www.2fz1.com/post/unity-ugui-autolayout/ uGUI知识点剖析之AutoLayout 前文详细介绍过RectTransform,RectTransf ...

  4. linux网络设备理解

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同. 1. 字符设备和块设备对应/dev下的一个设备文件.而网络设备不存在这样的设备文件.网络设备使用套接字socket访问,虽然也使用re ...

  5. Opencv2.2 移植到am335x-y开发板

    1.虚拟机上运行cmake-gui,报找不到文件,指示安装. 2.下载opencv2.2.0 http://opencv.org/downloads.html 3.cmake-gui,配置参考< ...

  6. bzoj 1670 [Usaco2006 Oct]Building the Moat护城河的挖掘——凸包

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1670 用叉积判断.注意两端的平行于 y 轴的. #include<cstdio> ...

  7. Zookeeper的shell操作

    一.客户端连接服务器 zkCli.sh start 二.命令操作 进入到客户端操作行,键入help 查看zookeeper命令列表 常用命令 1) 查看节点列表:ls 路径 2) 创建节点:creat ...

  8. Python学习总结之一 -- 基础篇

    Python学习第一篇 一:写在前面 啊,最近我的新博客一直都没有更新学习内容了,只是最近一直都在忙着寻找实习机会(或许这只是一个借口,真实原因是我太懒惰了,改改改!).终于今天又投递了几个新的实习职 ...

  9. zabbix 布署实践【8 监控windows server】

    参考http://www.cnblogs.com/likehua/p/3968689.html的思路,我安装的是zabbix 3.0 从zabbix官网下载windown的 Zabbix pre-co ...

  10. "Could not find the main class: org.apache.catalina.startup.Boostrap. Program will exit."

    尝试将 myeclipse中的编译版本修改(如,将1.5修改为1.6)