Web/14-前端性能优化/02-浏览器渲染机制.md
2021-07-29 11:08:52 +08:00

218 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 02-浏览器渲染机制
publish: true
---
<ArticleTopAd></ArticleTopAd>
## 前言
**渲染机制**包括的内容:
- 什么是DOCTYPE及作用
- 浏览器渲染过程。面试经常会问在浏览器中输入url发生了哪些事情。其中有一部就是浏览器的渲染过程。
- Reflow重排。面试官问完了渲染机制一般会紧接着问重排Reflow你可千万别说你没听过。
- Repaint重绘
- Layout布局。这里的Layout指的是浏览器的Layout。
## 什么是DOCTYPE及作用
### 定义
**DTD**Document Type Definition文档类型定义。
是一系列的语法规则用来定义XML或者(X)HTML文件类型。**浏览器会使用DTD来判断文本类型**决定使用何种协议来解析以及切换浏览器模式。说白了就是DTD就是告诉浏览器我是什么文档类型你要用什么协议来解析我
**DOCTYPE**用来声明DTD规范。
一个主要的用途便是文件的合法性验证。如果文件代码不合法那么浏览器解析时便会出现一些差错。说白了DOCTYPE就是用来声明DTD的
### 常见的DOCTYPE声明有几种
> 面试官紧接着会问,常见的 DOCTYPE 有哪些,以及 HTML5 的 DOCTYPE 怎么写。
1、**HTML 4.01 Strict**:(严格的)
```html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
```
PS该DTD包含所有的HTML元素和属性但不包括展示性的和弃用的元素比如 font、u下划线等这些是被废弃了的
2、**HTML 4.01 Transitional**:(传统的)
```html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
```
PS该DTD包含所有的HTML元素和属性但包括展示性的和弃用的元素比如 font、u下划线等
3、HTML 5
```html
<!DOCTYPE html>
```
**总结:**
面试时,不会让你写出 HTML 4.01的写法,因为大家都记不住。但是要记住 HTML 5 的写法,别看它简单,知道的人还真不多。
面试时,可以这样回答: HTML 4.01 中有两种写法,一种是严格的,一种是传统的;并且答出二者的区别。 HTML 5的写法是`<!DOCTYPE html>`。
## 浏览器的渲染过程
### 渲染树
![](http://img.smyhvae.com/20210118-2005.png)
> 上方图片的来源:[Google 官方 | 渲染树构建、布局及绘制](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=zh-cn)
**渲染树**包含了网页中有哪些节点、节点的从属关系、以及节点的CSS样式大小、颜色等
浏览器下载完html文档之后第一步是先将其解析成文本。而html标签是由一对一对的尖括号表述的可以被浏览器解析为有含义的标记。这些标记被翻译成节点对象存放到链型数据结构中。这些节点被称之为**DOM对象**,这个链型数据结构就是**渲染树**。
### 渲染过程(重要)
浏览器的渲染过程非常复杂,面试时找重点说就行,不然太耗时间。如何快速简洁地描述清楚,是关键。来看看下面这张图。
![](http://img.smyhvae.com/20180310_1257.png)
渲染过程中,涉及到以下几个概念:
- DOM树DOM Tree浏览器将HTML标签解析成树形的数据结构。DOM树包含了有哪些节点以及节点之间的从属关系嵌套关系
- CSSOMCSS Rule Tree浏览器将CSS解析成树形的数据结构。CSSOM包含了节点的CSS样式大小、颜色等
- 渲染树Render Tree: DOM 树与 CSSOM 树**合并**后形成渲染树。渲染树只包含渲染网页所需的节点(但并不知道位置)。
- 布局Layout: 计算出每个节点在屏幕中的**位置和大小**。
- 绘制Painting按照算出来的规则通过显卡把内容画出来。
- composite合成。浏览器在绘制的时候一开始不会把所有的内容都画在同一层上。需要把这些内容画在不同的曾上最终合并到一起并显示在屏幕上。
参考链接:
- [浏览器渲染原理及流程](http://www.cnblogs.com/slly/p/6640761.html)
### 关键渲染路径
说到渲染,就不得不提到“关键渲染路径”,它描述的是渲染从触发到绘制的过程。浏览器渲染经历了五个阶段:
> JavaScript/CSS --> Style --> Layout --> Paint --> Composite
![](http://img.smyhvae.com/20210118-1950.jpg)
> 上方图片的来源:<https://developers.google.com/web/fundamentals/performance/rendering>
关键渲染路径描述的是渲染从触发到绘制的全过程,一共经历了五个阶段:
1**触发视觉的变化:**通过JS、CSS代码来**触发**页面上的视觉变化。比如通过 jQuery添加节点、通过CSS添加动画都可以触发视觉上的变化。
2Style浏览器对样式进行计算。匹配选择器计算哪些CSS受到了影响。
3layout同上一段。
4painting同上一段。
5conmposite同上一段。
理论上,上面的五个步骤都是必须要经历的。布局和绘制是关键渲染路径中,最重要、开销最高的两个步骤。
但是,有些样式并不会影响布局,也不会影响绘制。所以,浏览器对这方面的性能进行了优化,并不一定要经历布局和绘制这两个过程。这就需要我们先了解一下「重排」和「重绘」这两个概念。详见下一段。
## 布局/回流/重排
### 定义
布局 layout
渲染对象在创建完成并添加到渲染树时是将DOM节点和它对应的样式结合起来并不包含位置和大小信息。
我们还需要通过 `Layout` 布局阶段,来计算它们在设备视口(viewport)内的确切位置和大小,计算这些值的过程称为`回流`、`布局`或`重排Reflow`。
参考链接:
- [从浏览器渲染原理,浅谈回流重绘与性能优化](https://www.cnblogs.com/xiahj/p/11777786.html)
- [你真的了解回流和重绘吗](https://github.com/chenjigeng/blog/issues/4)
### 什么时候会触发布局
DOM元素的**大小**和**位置**发生变化的时候,会触发布局。
- 增加、删除DOM元素
- display: none
- 移动元素位置,或是增加动画
- 修改CSS样式时宽高、display 为none等都是通过css样式来修改的
- offsetLeft、scrollTop、clientWidth
- 修改浏览器窗口大小时即Resize窗口移动端没有这个问题或是滚动的时候**有可能**会触发(具体要看浏览器的规则)。
- 修改网页的默认字体时(这个很消耗性能)。
**面试总结:**
首先要答出 Reflow 定义;其次,什么时候触发,至少要答出两条。更进一步,面试官可能还会问你**怎么避免reflow**,这个可以自己去查查。
## 绘制/重绘
### 定义
**绘制 paint**:当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器便把这些元素都按照各自的特性绘制一遍,于是页面的内容出现了,这个过程也称之为 Repaint重绘制
说白了,页面要呈现的内容,统统画在屏幕上,这就叫 Repaint。
### 什么时候触发绘制
- DOM改动
- CSS改动
其实就是判断当视觉上是否发生变化无论这个变化是通过DOM改动还是CSS改动。只要页面显示的内容不一样了肯定要 Repaint。
**面试总结:**
面试官经常会问:“如何**尽量减少**Repaint的频率
注意, reflow是问“怎么避免”repaint是问“怎么减少”。Repaint是无法避免的否则就成了静态页面了。
**答案**
1如果需要创建多个DOM节点可以使用**DocumentFragment**创建完然后一次性地加入document。加一个节点就repaint一次不太好
2将元素的display设置为”none”完成修改后再把display修改为原来的值。
参考链接:[如何减少浏览器repaint和reflow ?](http://blog.csdn.net/liaozhongping/article/details/47057889)