浏览器渲染的那些事儿

1. 浏览器渲染过程

1. 浏览器解析文件

  • 解析html,xhtml,svg这三类文档,形成dom树。
  • 解析css,产生css rule tree。
  • 解析js,js会通过api来操作dom tree和css rule tree。

2. 构建render树

  • rendering tree和dom tree并不完全相同,例如:或display:none的东西就不会放在渲染树中。
  • css rule tree主要是完成匹配,并把css rule附加给rendering tree的每个element。

3. 渲染树构建完成后

  • 浏览器会对这些元素进行定位和布局,这一步也叫做reflow或者layout。
  • 浏览器绘制这些元素的样式,颜色,背景,大小及边框等,这一步也叫做repaint。
  • 然后浏览器会将各层的信息发送给GPU,GPU会将各层合成;显示在屏幕上。

2. 重绘(repaint)和 重排(reflow)

1.重排

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

  • 页面渲染的初始阶段。
  • 浏览器尺寸变化时。
  • 元素尺寸发生改变。
  • 元素位置发生改变。
  • 元素的内容发生改变的时候。
  • 添加或者删除可见的DOM元素。
  • 动画效果进行计算和改变 CSS 属性值。
  • 伪类激活(:hover)

2. 重绘

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

3.性能优化

  • 多次改变样式属性操作合并成一次操作,减少DOM访问。
  • 需要批量操作dom时,用fragment脱离文档流,操作完后,载一次性返回。
  • 由于display:none的元素不再渲染树中,对隐藏的元素操作不会引起其他元素的重排。
  • 尽量不要在布局信息改变时做查询操作(会导致渲染队列强制刷新)。
  • 尽可能的为产生动画的 HTML 元素使用 fixed 或 absolute 的 position ,那么修改他们的 CSS 是不会 Reflow 的。
  • 不要通过 JS 逐条修改 DOM 的样式,提前定义好 CSS 的 Class 进行操作。

3. GPU是如何合成图像

GPU实际上可以看作一个独立的计算机,它有自己的处理器和存储器及数据处理模型。当浏览器向GPU发送消息的时候,就像向一个外部设备发送消息。

1. 浏览器向GPU发送的数据载体

  • 画每个复合层的图像。
  • 准备图层的数据。
  • 准备动画的着色器(如果需要)。
  • 向GPU发送数据。

2. 隐式合成

一个或多个没有自己复合层的元素要出现在有复合层元素的上方,它就会拥有自己的复合层;这种情况被称为隐式合成。
浏览器将一个元素提升为一个复合层有很多种原因,下面列举了一些:

  • 3d或透视变换css属性,例如translate3d,translateZ等等(js一般通过这种方式,使元素获得复合层)。
  • <video><iframe><canvas><webgl>等元素。
    
  • 混合插件(如flash)。
  • 元素自身的 opacity和transform 做 CSS 动画。
  • 拥有css过滤器的元素。
  • 使用will-change属性。
  • position:fixed,absolute。
  • 元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)。

3. GPU动画的优点和缺点

1. 优点
  • 每秒60帧,动画平滑、流畅。
  • 一个合适的动画工作在一个单独的线程,它不会被大量的js计算阻塞。
  • D“变换”是便宜的。
2. 缺点
  • 提升一个元素到复合层需要额外的重绘,有时这是慢的。(即我们得到的是一个全层重绘,而不是一个增量)。
  • 绘图层必须传输到GPU。取决于层的数量和传输可能会非常缓慢。这可能让一个元素在中低档设备上闪烁。
  • 每个复合层都需要消耗额外的内存,过多的内存可能导致浏览器的崩溃。
  • 如果你不考虑隐式合成,而使用重绘;会导致额外的内存占用,并且浏览器崩溃的概率是非常高的。
  • 我们会有视觉假象,例如在Safari中的文本渲染,在某些情况下页面内容将消失或变形。

4. 使用translateZ(0)提升性能的原理

使用transform和opacity做css动画时会隐式合成,将元素提升为一个复合层;而使用js操作css属性做动画时,必须使用translateZ或will-change才能将元素强行提升至一个复合层。,这样减少了元素变动时,浏览器的重新绘制区域。

5. 优化

  • 避免隐式合成,保持动画的对象的z-index尽可能的高,将元素上设置will-change CSS属性,元素上有了这个属性,浏览器会提升这个元素成为一个复合层(不是总是)。
  • 动画中只使用transform和opacity,transform和opacity保证了元素属性的变化不影响文档流、也不受文档流影响;并且不会造成repaint。
  • 减小复合层的尺寸。
  • 用css动画而不是js动画,css动画有一个重要的特性,它是完全工作在GPU上。因为你声明了一个动画如何开始和如何结束,浏览器会在动画开始前准备好所有需要的指令;并把它们发送给GPU。而如果使用js动画,浏览器必须计算每一帧的状态;为了保证平滑的动画,我们必须在浏览器主线程计算新状态;把它们发送给GPU至少60次每秒。除了计算和发送数据比css动画要慢,主线程的负载也会影响动画; 当主线程的计算任务过多时,会造成动画的延迟、卡顿。

https://segmentfault.com/a/1190000008015671

https://www.jianshu.com/p/fe64e387d5bc

https://sylvanassun.github.io/2017/10/03/2017-10-03-BrowserCriticalRenderingPath/

https://www.jianshu.com/p/e305ace24ddf

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值