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. Flask第二篇——服务器相关

    web服务器.应用服务器和web应用框架 web服务器:负责处理http请求.响应静态文件,常见的有Apache,Nginx以及微软的IIS 应用服务器:负责处理逻辑的服务器.比如php.python ...

  2. LeetCode 739. Daily Temperatures

    原题链接在这里:https://leetcode.com/problems/daily-temperatures/description/ 题目: Given a list of daily temp ...

  3. decorator and @property

    @property 首先, 它是个装饰器. 其次, 看到这个东西, 意味着它下面的函数可以被当作一个属性(成员变量)来看到.  通常, 这个函数会return点什么东西. 重点讲讲装饰器: 1, py ...

  4. django gunicorn 各worker class简单性能测试

    版权归作者所有,任何形式转载请联系作者.作者:petanne(来自豆瓣)来源:https://www.douban.com/note/564871723/ ====================== ...

  5. wordpress分享到微信无缩略图的问题

    牛逼的老板想把他牛逼的艺术品分享给牛逼的画家和藏家简直苦逼了我这个程序狗,他想要的结果是这样的qq和微信上依次为     但是牛逼的微信越来越“抠”了现在不是微信开发者用不了他的分享接口不给你显示缩略 ...

  6. XaaS简介(关于IssS,PaaS以及SaaS)

    IaaS,比较容易理解,提供了一个操作系统以及操作系统的硬件支撑:阿里云: PaaS,提供了一个平台,或者说,使用PaaS是希望能够在上面建立自己的服务/应用,同时平台会提供一些API或者工具,能够降 ...

  7. 生产环境LNMP (果图片)

    一. 下载一键安装包 LNMP   官方地址为:http://lnmp.org/ 登陆后运行:screen -S lnmp cd /usr/local/src wget -c http://soft. ...

  8. 运维命令:tcpdump

    tcpdump命令  tcpdump 命令是一款sniffer工具,它可以打印所有经过网络接口的数据包的头信息,也可以使用 -w 选项将数据包保存到文件中,方便以后分析. 常用参数: -a:尝试将网络 ...

  9. caffe读取多标签的lmdb数据

    问题描述: lmdb文件支持数据+标签的形式,但是却只能写入一个标签,引入多标签的解决方法有很多,这儿详细说一下我的办法:制作多个data数据,分别加入一个标签.我的方法只适用于标签数量较少的情况,标 ...

  10. Spring Framework中常见的事务传播陷阱(译文)

    最近看到Medium上一篇讨论Spring Framework中事务传播的文章,解释了几种常见的问题,解释的不错,这里直接翻译吧(意译为主,粗体和斜体是我自己加上的). 译文: 这是我的第一篇文章,我 ...