felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

浏览器的 reflow 和 repaint #127

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

《DOM 是 javaScript 与 HTML 页面进行对话的接口》中, 提到了 reflowrepaint 会引发浏览器性能问题。本篇主要来讲讲这个。

现今的三大框架中,都提倡要避免操作 DOM,为什么呢?因为操作 DOM 会影响性能慢。实际上这个性能不是慢在操作DOM过程本身,而是操作DOM之后, 浏览器的渲染引擎基本流程中的 reflowrepaint 要回流和重绘导致的。

reflowrepaint 是浏览器渲染引擎工作流的一部分,所以先来了解一下浏览器渲染引擎

一、 渲染引擎(The rendering engine)

浏览器有个叫渲染引擎的组件, 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTMLCSS 内容,并将解析后的内容显示在屏幕上。

渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。这是每一个浏览器的核心部分,所以渲染引擎也称为浏览器内核。

默认情况下,渲染引擎只可显示 HTMLXML 文档及图片。不过通过插件(或浏览器扩展程序),浏览器渲染引擎也可以显示其它类型的内容。例如,使用 PDF 查看器插件就能显示 PDF 文档。

2.1、渲染引擎简介

当前流行的FirefoxChromeSafari浏览器是基于两种渲染引擎构建的。Firefox 使用的是 Gecko,这是 Mozilla 公司“自制”的渲染引擎。而 SafariChrome(28版本以前)浏览器使用的都是 Webkit

2013年7月10日发布的 Chrome 28 版本中,Chrome 浏览器开始正式使用 Blink 内核。所以,Webkit 已经成为了 Chrome 浏览器的前内核。

Webkit 是一种开放源代码渲染引擎,起初用于 Linux 平台,随后由 Apple 公司进行修改,从而支持苹果机和 Windows。有关详情,请参阅 webkit.org

2.2、主流程(The main flow)

渲染引擎获取了文档内容之后,渲染引擎开始正式工作,如下图渲染引擎的基本流程:

值得注意的是,这个过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的 html 都解析完成之后再去构建和布局 render 树。它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。

图2.2为Webkit 主流程

图2.3为 MozillaGecko 渲染引擎主流程

从图2.2 和图2.3可以看出,虽然 WebkitGecko 使用的术语略有不同,但整体流程还是基本相同的。

二、reflow 和 repaint

从第一部分的浏览器引擎我们可以看出, reflowrepaint 分别在渲染引擎的基本流程的第三步和第四步。

2.1、reflow 回流

reflow 就是回流,它的影响比 repaint 大。它会在某一个 DOM 元素的位置发生改变后触发,而且它会重新计算所有元素的位置和在页面中的占有的面积,这样的话将会引起页面某一个部分甚至整个页面的重新渲染。改变某一个元素会影响它所有的子节点 (children)、祖先节点 (ancestors) 及兄弟节点(siblings)。

2.2、repaint 重绘

repaint 就是重绘,它会在你改变 DOM 元素的视觉效果时进行,改变布局时不会触发。比如,opacity, background-color, visibilityoutline等都会触发,重绘的开销还是比较昂贵的,因为浏览器会在某一个 DOM 元素的视觉效果改变后去 check 这个 DOM 元素内的所有节点。

2.3、reflow 和 repaint 都是浏览器慢的元凶

用户和 Web 页面都不能在 reflowrepaint 执行时做任何操作和响应,而且在极端的情况下,CSS 会拖慢 JS 的执行速度,这就是浏览器有的时候就是在操作之后没反应的原因之一。

绘制(repaint)是一个耗时的过程,然而布局(layout/reflow)是一个更耗时的过程,我们无法确定layout/reflow 一定是自上而下或是自下而上进行的,甚至一次layout/reflow会牵涉到整个文档布局的重新计算。

但是layout/reflow'是肯定无法避免的,所以我们主要是要最小化layout/reflow`的次数。

Reference