当我们请求页面的时候,拿到资源时,浏览器是怎么渲染的呢?这里我们就来了解一些浏览器渲染的过程。
关键词
- 渲染引擎:包括HTML解释器、CSS解释器、布局layout
- HTML解释器:解析HTML,构建DOM树
- CSS解释器:解析css,构建CSSOM
- 布局layout:对渲染树进行布局绘制
- js引擎:解析JavaScript
认识完关键词之后,我们来看一下浏览器是怎么将html、css、js文件,渲染到页面上的。
首先当然是请求html文件,拿到html文件之后,浏览器就可以对文件进行解析处理。
构建DOM树
拿到html文件之后,HTML解释器会先对拿到的数据进行响应的编码,转成自己想到的格式。
然后就开始构建DOM树,为什么是树结构呢?前端的同学应该都很好理解,因为html结构本身就是一个树形结构,所以树是html很好的表现形式。
我们来看html的hello world,从锁进格式就可以看出html的DOM树。
<html lang="en">
<head>
<title>title</title>
</head>
<body>
<div>hello world</div>
</body>
</html>
构建CSSOM(CSS规则树)
接着,我们来看css,CSSOM是由css规则树来处理的。
拿到css数据之后,CSS解释器就开始构建CSSOM。
因为css的规则是需要给html节点配置的,所以也是一棵树的形状。
html {
color: #ffffff;
}
body {
font-size: 14px;
}
渲染树
有来DOM树和CSSOM之后,其实还不是最后需要渲染的东西,因为有些标签其实是不需要显示的,比如head内容,比如display:none;的内容。
所以,这里渲染引擎会将DOM树和CSSOM合成一棵渲染树。
我们可以看到下面这张图片,这就是渲染树的组合流程。
布局 & 绘制
有了渲染树之后,浏览器要怎么把渲染树画到浏览器上呢?
渲染树其实是一个树结构,还没有进行实例的结构布局,所以,布局这里就根据渲染树的结构样式,对盒子宽高进行计算,整体结构布局。
布局完成之后,浏览器就要把布局结构绘制到浏览器上。
js文件呢?几乎所有的页面都会有js脚本,不然没有办法与用户/服务器进行交互,下面我们来看看js脚本。
js引擎
js引擎,看到这个名字,我们就可以理解,用来执行js脚本用的。目前chrome用的是javascript v8引擎,node使用的也是javascript v8引擎。
为什么这里要讲到js引擎呢?因为js脚本有可能会阻塞浏览器的渲染。
阻塞渲染
相信前端同学写页面的时候都有一个习惯,就是把js放到html文件的最下面。
为什么呢?为来不阻塞浏览器渲染。
<!--阻塞-->
<html lang="en">
<head>
<title>Document</title>
<script src="./binnie.js"></script>
</head>
<body>
<div>hello world</div>
</body>
</html>
<!--非阻塞-->
<html lang="en">
<head>
<title>Document</title>
// defer脚本会在页面渲染完成才执行js脚本
<script src="./binnie.js" defer></script>
</head>
<body>
<div>hello world</div>
<script src="./binnie.js"></script>
</body>
</html>
我们知道,js脚本可以操作DOM结构,也可以操作CSS,所以执行js脚本时,浏览器会停止DOM和CSSOM的构建。
构建DOM树过程中,如果遇到 script 标签,那么DOM构建过程会停止并且等待js脚本执行完毕。
当js脚本操作css时,由于需要操作CSSOM,所以这里会等到CSSOM完成构建完成之后,才继续执行js脚本。
重绘 & 重排
页面第一次渲染的时候,会绘制初始化的页面,当页面结构发生改变时,浏览器也会重新对页面进行绘制&渲染,也就是重绘&重排。
- 重排:当盒子位置&大小发生变动时,会触发重排
- 重绘:当盒子内容发生变化时,会触发重绘
重绘不一定会重排,但是重排一定会触发重绘。
写在最后
了解浏览器的渲染机制,我们在项目优化过程中,可以针对其机制,进行项目优化,加快页面渲染过程~