共计 4343 个字符,预计需要花费 11 分钟才能阅读完成。
大家好,我是桃翁
最近在面试的时候常常会问:如何了解重排和重绘?
我发现很多候选人都没有答道关键点上,感觉是在哪里看到过相干的文章,听起来零零散散,毫无逻辑。
谬误示范
个别的面试过程就是这样的:
面试官:如何了解重排和重绘?
候选人:重排就是当页面的构造发生变化了,就会重排,比方扭转变字体的大小,增删 DOM 元素这样的。重绘就是页面构造没有变动,只是外观变了,比方改了一下字体色彩、背景色彩这样的。就只会产生重绘。
当然他说的也没错,我也不能间接说他错,就持续疏导
面试官:那重排和重绘有什么关系吗?
候选人:重排肯定会导致重绘,重绘不肯定会导致重排。
面试官:为什么呢?
候选人:因为重排构造发生变化了嘛,必定会导致重绘。
我这时候表情就是这样:
如果你感觉下面的答复很实在,那上面的你确定得好好看看。
接下来个别我不会间接跳过,我会再问一下浏览器要害渲染门路疏导一下。
如果不晓得的话,我会再疏导一下(这个时候其实根本曾经放弃了)。
问一下你晓得当浏览器加载到一个 HTML 会产生什么事件吗?
如果还是不晓得的话,这下一题了。
如果晓得要害渲染门路的,根本疏导一下还是能够搞明确,如果不分明的,必定是了解不了重排和重绘的。
考点
这道题我个别考查两个点:
- 浏览器的要害渲染门路。如果答不到这下面,个别这个题就凉了。
- 性能优化,如果缩小重绘和回流,当然这个点必定也是要基于对 要害渲染门路 的了解(这点不是关键点)。
温习
温习的目标是为了晓得考点是啥,简略的给大家温习一下,更具体的内容心愿按我介绍的知识点(能够看我文末举荐的文章进行深刻学习),毕竟温习不是上课。
咱们能够能晓得,写了 HTML、CSS、JavaScript 就能够将页面渲染到屏幕上,然而浏览器是如何把咱们的代码渲染到屏幕上的像素点的呢?这就须要理解到这么一个概念 CRP:
要害渲染门路 (Critical Rendering Path) 是浏览器将 HTML,CSS 和 JavaScript 转换为屏幕上的像素所经验的步骤序列。优化要害渲染门路可进步渲染性能。
大抵步骤是这样:在解析 HTML 时会创立 DOM,HTML 能够申请 JavaScript,而 JavaScript 反过来,又能够更改 DOM。HTML 蕴含或申请款式,顺次来构建 CSSOM。
浏览器引擎将两者联合起来以创立 Render Tree (渲染树),Layout(布局)确定页面上所有内容的大小和地位,确定布局后,将像素 Paint (绘制)到屏幕上。
优化要害渲染门路能够缩短首次渲染的工夫。理解和优化要害渲染门路对于确保 重排 和重绘 能够每秒 60 帧的速度进行,以确保高效的用户交互并防止厌恶是很重要的。
接下来钻研一下具体的过程:
步骤
1. 生成 DOM
DOM 构建是增量的。浏览器从近程下载 Byte
=> 依据相应的编码 (如 utf8) 转化为 字符串
=> 通过 AST 解析为 Token
=> 生成 Node
=> 生成 DOM
。
单个 DOM 节点以 startTag token 开始,以 endTag token 完结。节点蕴含无关 HTML 元素的所有相干信息。该信息是应用 token 形容的。节点依据 token 层次结构连贯到 DOM 树中。
如果另一组 startTag 和 endTag token 位于一组 startTag 和 endTag 之间,则在节点内有一个节点,这就是咱们定义 DOM 树层次结构的形式。
2. 生成 CSSOM
浏览器解析 css 文件,生成 CSSOM。CSSOM 蕴含了页面所有的款式,也就是如何展现 DOM 的信息。
CSSOM 跟 DOM 很像,然而不同。
DOM 结构是增量的,CSSOM 却不是。CSS 是渲染阻塞的:浏览器会阻塞页面渲染直到它接管和执行了所有的 CSS。
CSS 是渲染阻塞是因为规定能够被笼罩,所以内容不能被渲染直到 CSSOM 的实现。
3. Render Tree
渲染树 (Render Tree) 包含了内容和款式:DOM 和 CSSOM 树联合为渲染树。
为了结构渲染树,浏览器查看每个节点,从 DOM 树的根节点开始,并且决定哪些 CSS 规定被增加。
渲染树只蕴含了可见内容(body 里的局部)。
Head(通常)不蕴含任何可见信息,因而不会被蕴含在渲染树种。如果有元素上有 display: none;
,它自身和其后辈都不会呈现在渲染树中。
4. Layout
一旦渲染树被构建,布局变成了可能。布局取决于屏幕的尺寸。布局这个步骤决定了在哪里和如何在页面上搁置元素,决定了每个元素的宽和高,以及他们之间的相关性。
提醒:一个页面渲染在不同尺寸的屏幕上,比方渲染在挪动端和 PC 端上,展现有差别,在后面的步骤都是不变的,只有在布局的时候才会依据屏幕尺寸进行差异化解决。
5. Paint
最初一步是将像素绘制在屏幕上,栅格化所有元素,将元素转换为理论像素。
一旦渲染树创立并且布局实现,像素就能够被绘制在屏幕上。加载时,整个屏幕被绘制进去。之后,只有 受影响的屏幕区域会被重绘,浏览器被优化为只重绘须要绘制的最小区域。
绘制工夫取决于何种类型的更新被附加在渲染树上。绘制是一个十分快的过程,所以聚焦在晋升性能时这大略不是最无效的局部
重排 (Reflow) 和重绘(Repaint)
理解完下面的要害门路渲染之后,再来理解重排和重绘几乎就是小 case。
重排 (Reflow):元素的 地位产生变动 时产生重排,也叫回流。 此时在 Layout 阶段,计算每一个元素在设施视口内的确切地位和大小。当一个元素地位发生变化时,其父元素及其后边的元素地位都可能发生变化,代价极高。
在答复什么是重排的时候,要害不是地位产生变动,这只是起因(Why),而不是 What。What 是从新计算每个元素在设施视口内的确切地位和大小。
重绘 (Repaint): 元素的 款式产生变动 ,然而地位没有扭转。 此时在要害渲染门路中的 Paint 阶段,将渲染树中的每个节点转换成屏幕上的理论像素,这一步通常称为绘制或栅格化。
而答复什么是重绘的关键点在于在要害渲染门路中的 Paint 阶段,将渲染树中的每个节点转换成屏幕上的理论像素,这才是 What。
JavaScript 与要害门路渲染
后面聊步骤的时候根本都是聊的 HTML、CSS 与 CRP 的关系,最初再聊一下 JS 与 CRP 的关系,再看一下文章结尾的这个图。
JavaScript 的执行是在生成渲染树之前的。这也是为什么 JavaScript 的加载、解析与执行会阻塞 DOM 的构建,阻塞页面的渲染。
这其实是十分正当的
因为 JavaScript 能够批改网页的内容,它能够更改 DOM,如果不阻塞,那么这边在构建 DOM,那边 JavaScript 在改 DOM,如何保障最终失去的 DOM 是否正确?
而且在 JS 中前一秒获取到的 DOM 和后一秒获取到的 DOM 不一样是什么鬼?它会产生一系列问题,所以 JS 是阻塞的,它会阻塞 DOM 的构建流程,所以在 JS 中无奈获取 JS 前面的元素,因为 DOM 还没构建到那。
这就是为什么咱们须要把 js 放在页面底部的起因,尽量保障 DOM 树生成结束再去加载 JS,从而呈现这样的成果。
性能优化
基于以上的剖析,简略的说几条性能优化的形式,本人能够去剖析一下为什么这些形式能够做性能优化。
- 缩小 DOM 树渲染工夫(譬如升高 HTML 层级、标签尽量语义化等等)
- 缩小 CSSOM 树渲染工夫(升高选择器层级等等)
- 缩小 HTTP 申请次数及申请大小
- 将 css 放在页面开始地位
- 将 js 放在页面底部地位,并尽可能用 defer 或者 async 防止阻塞的 js 加载,确保 DOM 树生成完才会去加载 JS
- 用 link 代替 @import
- 如果页面 css 较少,尽量应用内嵌式
- 为了缩小白屏工夫,页面加载时先疾速生成一个 DOM 树
正确的性能优化思路
再啰嗦一下性能优化相干的,当你遇到一个性能问题的时候,相对不是去网上找一些性能优化的办法,而后不管三七二十一,就整下来,这样大概率是没啥用的。
第一件事件,肯定是要先剖析性能的瓶颈在哪里。
第一件事件,肯定是要先剖析性能的瓶颈在哪里。
第一件事件,肯定是要先剖析性能的瓶颈在哪里。
比方你遇到了首屏加载的性能问题,你就要依据开发者工具,比方看 network 是否是因为资源体积太大导致申请慢,还是后端解决慢,还是资源太多了加载慢.
如果这些都不是,可能是因为 渲染慢,再去剖析 performce 面板,看一下是 js 执行慢,还是啥起因。
再比方你遇到了 webpack 的性能问题,比方打包的资源太大了,你要去解决这个问题,你也不应该间接去轻易找几个优化的办法就开始整。
而是先应该通过 webpack-bundle-analyzer 插件去剖析包大的起因是什么?
- 是依赖包太大了,没有做按需加载?
- 还是反复的打包了几个版本的雷同依赖?
- 还是因为 src 太大了,是否须要做个动静加载?
- 还是因为其余的,通过 webpack-bundle-analyzer 剖析进去的组成内容去找问题。
最初再总结一下,遇到问题应该先通过各种剖析工具,找到呈现性能瓶颈的起因,再依据这个起因去寻找对应的优化形式,要隔靴搔痒。
不论是面试的时候答复,还是本人平时在解决问题的时候都要这样,只有剖析出问题了,解决方案一大堆,找不到问题,瞎搞就是浪费时间。
参考答复
我置信温习完之后,对这个知识点应该是分明了,面试的时候不须要说这么多,把关键点说进去,让面试官晓得你是懂的就行,如果面试官有趣味的话会持续诘问的,这个时候再具体的跟他介绍诘问的点。
如果是我被问到这个题,我的答复大略是这样的,仅供参考:
重排和重绘是浏览器要害渲染门路上的两个节点,浏览器的要害渲染门路就是 DOM 和 CSSOM 生成渲染树,而后依据渲染树通过一个布局 (也叫 layout) 步骤来确定页面上所有内容的大小和地位,确定布局后,将像素 绘制 (也叫 Paint)到屏幕上。
其中重排就是当元素的地位产生变动的时候,浏览器从新执行布局这个步骤,来从新确定页面上内容的大小和地位,确定完之后就会进行从新绘制到屏幕上,所以重排肯定会导致重绘。
如果元素地位没有产生变动,仅仅只是款式产生变动,这个时候浏览器从新渲染的时候会跳过布局步骤,间接进入绘制步骤,这就是重绘,所以重绘不肯定会导致重排。
下面这样答复,我感觉在绝大部分面试官那里曾经能够拿到这个题的分了。
不过面试官还是有可能持续往深的问,小伙伴们能够在评论区说一说你们还遇到过哪些相干的问题,我前面再持续帮忙大家一起剖析。
对于性能问题上,缩小重绘和回流感觉没有那么重要,因为优化个别状况不是很显著,不答问题也不大,更多的性能优化是在整个链路上的优化,比方性能优化题目外面的那 8 个点。
最初
在行业不景气的时候,心愿大家都能顺利找到适合的工作。
对于要害门路渲染和重排、重绘,我最初还是忍不住给大家举荐一下大漠老师的两篇文章,有空去拜读一下子。
- 要害渲染门路(CRP)
- 了解 Web 的重排和重绘
参考文章:
- 要害渲染门路
- developers.google.cn:要害渲染门路