网页内容的组成
1、Doctype: 提供浏览器HTML版本信息
2、Head: html的头部
-> meta: 元数据信息
-> charset: 此特性声明当前文档所使用的字符编码
-> http-equiv: 客户行为,如渲染模式,缓存等
-> name[keyword]: 搜索引擎使用
-> name[description]: 搜索引擎使用
-> name[viewport]: 浏览器视口设置(content):
-> link: 引入的css样式
-> script: 需要在body钱完成加载或者运行的脚本
-> style: 样式(内联样式)
3、body: html实体
-> head,foot,div,h1~6,p,span,a,b,br,ul,ol,li等: HTML内容布局构成标签
-> script: 需要在body解析时加载或者运行的脚本
浏览器渲染网页需要做的工作

HTML解析器: 解释HTML文本的解释器.把HTML文本解析成DOM树.(HTML->DOM)
CSS解析器: 遇到级联样式是,需要使用级联样式表解释器.为DOM对象计算出样式信息.(CSS=>CSSOM(构成层叠样式表模型))
JAVASCRIPT引擎: 遇到js代码时,需要使用javascript解释器,并使得js代码有调用DOM接口和CSSOM接口的能力.
布局: 结合CSS,计算出每个DOM对象的大小位置信息.
DOM树+CSSOM(成层叠样式表模型 = 合并成渲染树(rendering Tree)
绘图: 将经过布局计算出的DOM节点绘制成图像.
以上重要组件组成了浏览器渲染引擎

通过响应的内容,我们可以看到内容中还存在许多外联资源,浏览器是如何处理的?
不同的外联资源,webkit中有不同的资源加载器.当浏览器解析到URL地址时,调用特定的资源加载器.如果不是特殊资源,加载过程不会阻碍渲染过程.
为什么css要放在头部,js放在尾部?
一般来说css资源不会阻碍渲染过程,但是javascript资源在旧版浏览器中,会阻碍渲染过程的执行,如果放置在头部,渲染过程会暂停,造成"白屏".但是现在浏览器的优化已经坐的很好了,所以当渲染过程被阻塞是,浏览器会开启新的线程继续渲染
浏览器在渲染之前和之后还要做哪些事情?
渲染之前需要加载资源,渲染之后在DOM或者CSS变化后,重新进行布局和重新渲染操作
浏览器渲染网页的流程
dom树的构建原理:
解析html采用的是符号识别算法,简单说来,就是把html中的每个标签都识别为一个符号,规范中给每个符号定义了相对应的dom元素,所以这些符号被树构造器处理成,对应的dom元素。最后这些元素会被添加到dom树上。
对css文件解析会生成css规则,css规则与dom树结合之后生成渲染树。构建好渲染树之后是布局渲染树。最后是绘制渲染树。
1.构建DOM树
当浏览器客户端从服务器那接受到HTML文档后,就会遍历文档节点然后生成DOM树,DOM树结构和HTML标签一一对应.
DOM树在构建的过程中可能会被CSS和JS的加载而执行阻塞
display:none的元素也会DOM树中.
注释也会在DOM树中
script标签会在DOM树中
2.CSS解析
浏览器会解析CSS文件并生成CSS规则树,在过程中,每个CSS文件都会被分析成StyleSheet对象,每个对象都包括CSS规则,CSS规则对象包括对应的选择器和声明对象以及其他对象.
CSS解析可以与DOM解析同时进行
CSS解析和script的执行是互斥的
在webkit内核中进行了script执行优化,只有JS访问css时才会发生会斥.
3.构建渲染树
通过DOM树和CSS规则树,浏览器就可以通过它们供应舰渲染树了.浏览器会先从DOM树的根节点开始遍历每个可见节点,然后对每个可见节点找到适配的CSS样式规则并应用,构建成DOM.

Render Tree和DOM Tree不完全对应
display:none的元素不在render Tree中
visiblity:hidden的元素在render Tree中
4.渲染树布局
布局阶段会从渲染树的根节点开始遍历,由于渲染树上的每一个节点都是一个render Object对象,包括高,位置等样式信息.所以浏览器就可以通过这些样式信息来确定每个节点对象在页面上的确切大小和位置,布局阶段的输出就是我们常说的盒子模型,他会精确的捕获每个元素在屏幕内确切的位置与大小.
float,absolute,fixed等会脱离文档流
5.渲染树绘制(Painting the render tree)
在绘制阶段,浏览器会遍历渲染树,调用浏览器的paint()方法在屏幕上显示内容.渲染树的绘制工作是有浏览器的UI后端组件完成的.
重排(回流)和重绘
重排(回流)
当DOM的变化引发了元素的几何属性变化(改变元素的width,height,margin,padding,border,display:block、none等),导致浏览器得重新计算元素的集合属性,并重新渲染DOM树,这个过程就叫做重排.重排之后会重新绘制.
重绘
重排之后要重新渲染或者改变元素的不会引起几何变化的(改变元素的color,background等),这样的过程就叫做重绘.
重排一定会引起重绘,重绘不一定会引起重排.
什么操作下会引起重排呢?
1.页面渲染树初始化(这个无法避免)
2.元素的位置改变,高度,宽度,position等的变化
3.内容的改变
4.添加或者删除可见的DOM元素,display:block与display:none之间的切换.
5.浏览器窗口大小的改变
6.
什么操作下会引起重绘呢?
1.改变元素的颜色,背景,边框颜色
重排优化
1.将多次改变样式属性的操作合并成一次操作,减少DOM访问。
2.如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排。(fragment元素的应用)
3.将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
4.由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发两次重排。
5.在内存中多次操作节点,完成后再添加到文档中去。例如要异步获取表格数据,渲染到页面。可以先取得数据后在内存中构建整个表格的html片段,再一次性添加到文档中去,而不是循环添加每一行。
6.尽量不要使用table布局。
7.使用虚拟DOM的脚本库.如vue和react.