学而不思则惘,思而不学则殆
css
前几天接到一个页面效果优化的任务,边作边查阅了一些关于页面性能的资料。作完任务以后,抽空写了一篇总结,梳理一下思路,加深本身的理解。html
先思考这样的一个问题:web
什么叫页面性能好?如何进行评判?chrome
直观上讲,咱们一般会经过一个页面流不流畅来判断一个页面的性能好很差。可是开发中,总不能这么随意吧。canvas
FPS(frame per second),即一秒之间可以完成多少次从新渲染.segmentfault
网页动画的每一帧(frame)都是一次从新渲染,每秒低于24帧
的动画,人眼就能感觉到停顿。通常的网页动画,须要达到每秒30帧到60帧的频率,才能比较流畅
。浏览器
而大多数显示器的刷新频率是60Hz
,为了与系统一致,以及节省电力,浏览器会自动按照这个频率,刷新动画。因此,若是网页可以作到每秒60帧,就会跟显示器同步刷新,达到最佳的视觉效果。这意味着,一秒以内进行60次从新渲染,每次从新渲染的时间不能超过16.66ms
。性能优化
在实际的开发,只要达到30fps就能够了网络
强大的chrome给咱们提供了一个工具,叫作timeline,在帧模式下,咱们能够看到代码的执行状况frontend
柱状'frame':表示渲染过程当中的一帧,也就是浏览器为了渲染单个内容块而必需要作的工做,包括:执行js,处理事件,修改DOM,更改样式和布局,绘制页面等。帧柱的高度表示了该帧的总耗时,帧柱中的颜色分别对应该帧中包含的不停类型的事件。咱们的目标就是控制其在30fps,即1000ms / 30 = 33.34ms
蓝色: 网络和HTML解析
黄色: JavaScript 脚本运行
紫色: 样式重计算和布局 ( Layout , Recaculate Style, Update Layer tree)
绿色: 绘制和合成 ( Paint , Composite Layers)
30fps和60fps的基准线,能够直观地看到页面每一帧的状况
灰色区块:那些没有被DevTools感知到的活动
空白区块:显示刷新周期(display refresh cycles)中的空闲时间段??
event :事件,上面能够看到触发了什么的事件,而后执行的语句是哪些,
recalculate style: 从新计算样式
update layer tree: 【耗时】
composite layers: 【耗时】
paint X n: 【耗时】
接下来思考这个问题:
什么是update layer tree,什么是compsite layers,它们为何那么耗时?
要理解update layer tree
和composite layers
,咱们必须了解页面的渲染原理和过程。
咱们都知道网页生成过程,大体能够分红五步
HTML代码转化为DOM
CSS代码转化成CSSOM(CSS Object Model)
结合DOM和CSSOM,生成一棵渲染树(包含每一个节点的视觉信息)
生成布局(layout),即将全部渲染树的全部节点进行平面合成
将布局绘制(paint)在屏幕上
那么,浏览器是如何进行渲染的?
浏览器在渲染一个页面时,会将页面分为不少个图层,图层有大有小,每一个图层上有一个或多个节点。浏览器实际所作的工做有:
获取DOM后分隔为多个图层
对每一个图层的节点计算样式结果(recalculate style)
为每一个节点生成图形和位置(layout即reflow和重布局)
将每一个节点绘制填充到图层位图汇总(paint,repaint)
图层做为纹理加载到GPU
合并多个图层到页面上,生成最终图像(composite layers)
渲染的过程一般是至关耗时,低效的代码每每就是触发过程的layout,paint,composite layers,致使页面卡顿。
明白了整个渲染的过程和timeline的操做的含义,那么能够思考这样的一个问题:
什么样的代码会触发这么耗时的操做,致使咱们的页面卡顿?
网页生成的时候,至少会渲染一次。而咱们须要关注的是用户访问过程当中,那些会致使网页从新渲染的行为:
修改DOM
修改样式表
用户事件(例如鼠标悬停,页面滚动,输入框输入文字等)
从新渲染,就涉及重排
和重绘
重排(reflow)
即从新生成布局,重排必然致使重绘,如元素位置的改变,就会触发重排和重绘。
会触发重排的的属性:
盒子模型相关属性会触发重布局:
width
height
padding
margin
display
border-width
border
min-height
定位属性及浮动也会触发重布局:
top
bottom
left
right
position
float
clear
改变节点内部文字结构也会触发重布局:
text-align
overflow-y
font-weight
overflow
font-family
line-height
vertival-align
white-space
font-size
重绘(repaint)
即从新绘制,须要注意的是,重绘不必定须要重排
,好比改变某个元素的颜色,就只会触发重绘,而不会触发重排。
会触发重绘的属性
color
border-style
border-radius
visibility
text-decoration
background
background-image
background-position
background-repeat
background-size
outline-color
outline
outline-style
outline-width
box-shadow
手机就算重绘也很慢
重排和重绘会不断触发,这是不可避免的,可是它们很是消耗资源,是致使网页性能低下的根本缘由。
提升网页性能,就是要下降重排和重绘的频率和成本,尽可能少触发从新渲染
。
大部分浏览器经过队列化修改
和批量显示
优化重排版过程。然而有些操做会强迫刷新并要求全部计划改变的部分马上应用。
1. 建立图层有什么用?
咱们知道浏览器layout和paint是在每个图层上进行的,当有一个元素常常变化,为了减小这个元素对页面的影响,咱们能够为这个元素建立一个单独的图层,来提供页面的性能。
2. 在何时会建立图层?
3D或透视变换(perspective transform)CSS属性(例如translateZ(0)/translate3d(0,0,0))
使用加速视频解码的<video>节点
拥有3D(WebGL)上下文或加速的2D上下文的<canvas>节点
混合插件(如Flash)
对本身的opacity作CSS动画或使用一个动画webkit变换的元素
拥有加速CSS过滤器的元素
元素有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在本身的层里)
元素有一个z-index较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)
position为fixed也会建立图层,而absolute则不会
3. 建立图层的弊端
图层的建立也须要必定的开销,太多的图层会消耗过多的内存。这可能致使出现预期以外的行为,可能会致使潜在的崩溃。
1. 什么是硬件加速?
现代浏览器大均可以利用GPU来加速页面渲染。在GPU的众多特性之中,它能够存储必定数量的纹理(一个矩形的像素点集合)而且高效地操做这些纹理(好比进行特定的移动、缩放和旋转操做)。这些特性在实现一个流畅的动画时特别有用。浏览器不会在动画的每一帧都绘制一次,而是生成DOM元素的快照,并做为GPU纹理(也被叫作层)存储起来。以后浏览器只须要告诉GPU去转换指定的纹理来实现DOM元素的动画效果。这就叫作GPU合成,也常常被称做硬件加速
。
2. 怎么启用硬件加速?
CSS animations, transforms 以及 transitions 不会自动开启GPU加速,而是由浏览器的缓慢的软件渲染引擎来执行。那咱们怎样才能够切换到GPU模式呢,不少浏览器提供了某些触发的CSS规则。
translate3d(0,0,0)
rotate3d(0,0,0,0)
scale3d(0,0,0)
translateZ(0)【可能】
只须要在css中使用这类属性,便可开启硬件加速
3. 硬件加速真的那么好吗?
从本人在移动端开发的实践来看,硬件加速是比较坑的。开启硬件加速会占有手机过多的内存而致使手机卡顿(这个时候页面也确定卡顿了),所以在咱们团队中,是禁止掉硬件加速的。
具体的原理能够参考连接5
作完这个任务以后, 才以为本身真正是在作开发。严谨细致的工匠精神,把控好本身的每一行代码。面对复杂的问题,一步步分析状况,查阅资料,不断地debug,感受提升很多。但愿本身继续加油,也与抽空看这篇文章的你共勉。