文章目录
前言
相关问题
- 浏览器如何渲染页面
- 有哪些提高浏览器渲染性能的方法
一、浏览器渲染的基本流程?
不同的浏览器内核不同,所以渲染过程不太一样。虽然主流浏览器渲染过程叫法有区别,但是主要流程还是相同的。下面就WebKit
主流程:
1.1 HTML解析出DOM Tree
HTML Parser
的任务是将HTML
标记解析成DOM Tree
,举个🌰,下面这段html代码
<html>
<head>
<title>web page parsing</title>
</head>
<body>
<div>
<h1>web page parsing</h1>
<p>this is an example</p>
</div>
</body>
</html>
经过解析之后的DOM Tree大概是:
1.2 CSS解析出Style Rules
CSS Parser
将CSS
解析成Style Rules
,Style Rules
也叫CSSOM
(CSS Object Model)。StyleRules
也是一个树形结构,根据CSS
文件整理出来的类似DOM Tree
的树形结构。
浏览器解析文档,当遇到<script>
标签的时候,会立即解析脚本,停止解析文档(因为JS可能会改动DOM和CSS
,所以继续解析会造成浪费)。 如果脚本是外部的,会等待脚本下载完毕,再继续解析文档。现在可以在script
标签上增加属性defer或者async
。 脚本解析会将脚本中改变DOM和CSS
的地方分别解析出来,追加到DOM Tree
和Style Rules
上。
1.3 Render Tree
Render Tree
是和 DOM
元素相对应的,但并非一一对应。Render Tree
实际上就是一个计算好样式与HTML
对应的(包括哪些显示,那些不显示)的Tree
。
1.4 Layout布局
创建渲染树后,下一步就是布局(Layout
),或者叫回流(reflow,relayout
),这个过程就是通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸,将其安置在浏览器窗口的正确位置,而有些时候我们会在文档布局完成后对DOM
进行修改,这时候可能需要重新进行布局,也可称其为回流,本质上还是一个布局的过程,每一个渲染对象都有一个布局或者回流方法,实现其布局或回流。
对渲染树的布局可以分为全局和局部的,全局即对整个渲染树进行重新布局,如当我们改变了窗口尺寸或方向或者是修改了根元素的尺寸或者字体大小等;而局部布局可以是对渲染树的某部分或某一个渲染对象进行重新布局。
布局是一个从上到下,从外到内进行的递归过程,从根渲染对象,即对应着HTML文档根元素,然后下一级渲染对象,如对应着元素,如此层层递归,依次计算每一个渲染对象的几何信息(位置和尺寸)
1.5 painting(绘制)
在绘制阶段,系统会遍历Render Tree
,并调用呈现器的paint
方法,将呈现器的内容显示在屏幕上。
在绘制阶段涉及到两个考点重绘和回流(重排)
重绘:当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility
等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘
回流:无论通过什么方式影响了元素的几何信息(元素在视口内的位置和尺寸大小),浏览器需要重新计算元素在视口内的几何属性,这个过程叫做回流。
二、浏览器渲染性能的优化
2.1减少渲染中的重排重绘
回流的开销是比较大的,那么怎么减少回流呢?
什么操作会造成回流:
- 页面首次渲染
- 浏览器窗口大小发生改变
- 元素尺寸或位置发生改变
- 元素内容变化(文字数量或图片大小等等)
- 元素字体大小变化
6 .添加或者删除可见的DOM元素
7 .激活CSS伪类(例如::hover) - 查询某些属性或调用某些方法
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、offsetHeight、offsetTop、offsetLeft
scrollWidth、scrollHeight、scrollTop、scrollLeft
scrollIntoView()、scrollIntoViewIffNeeded()
getComputedStyle()【IE】
scrollTo()
如何减少回流:
css
- 避免使用table布局;
- 尽可能在DOM树的最末端改变class;
- 将动画效果应用到position属性为absolute或fixed的元素上:使它脱离文档流,否则会引起父元素及后续元素频繁回流
- 避免使用CSS表达式(例如:calc())。
- 开启 **GPU 加速,**利用 css 属性
transform
等,比如改变元素位置,我们使用translate
会比使用绝对定位改变其left 、top
等来的高效,因为它不会触发重排或重绘,transform 使浏览器为元素创建⼀个GPU
图层,这使得动画元素在一个独立的层中进行渲染。当元素的内容没有发生改变,就没有必要进行重绘。
JS
- 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
- 避免频繁操作DOM,创建一个
documentFragment
,在它上面应用所有DOM操作,最后再把它添加到文档中。 - 也可以先为元素设置
display: none
,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。 - 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
2.2 优化影响渲染的资源
在浏览器解析 HTML
的过程中,CSS 和 JS 都有可能对页面的渲染造成影响。优化方法包括以下几点:
- 关键 CSS 资源放在头部加载。
- JS 通常放在页面底部。
- 为 JS 添加 async 和 defer 属性。
- body 中尽量不要出现 CSS 和 JS。
- 为 img 指定宽高,避免图像加载完成后触发重排。
- 避免使用
table, iframe
等慢元素。原因是table
会等到它的dom
树全部生成后再一次性插入页面中;iframe
内资源的下载过程会阻塞父页面静态资源的下载及css, dom
树的解析。