前言
作为一名前端工程师我们有必要知道浏览器是怎样将我们写的HTML、CSS以及JS转换成我们眼睛所见到的花花绿绿的文字及图片的。
这也是我《前端系统性学习》专栏的开篇第一讲,后面还会有一系列的基础或一些深究原理的文章,欢迎大家关注。
正文
1、思考问题: 从输入 URL 到页面加载完成的过程中都发生了什么事情?
1. 输入地址
2. 浏览器查找域名的IP地址
3. 浏览器向web服务器发送一个HTTP请求
4. 服务器的永久重定向响应
5. 浏览器跟踪重定向地址
6. 服务器处理请求
7. 服务器返回一个 响应
8. 浏览器显示HTML
9. 浏览器发送请求获取嵌入在HTML中的资源(如图片、音频、视频、CSS、js等等)
10. 浏览器发送异步请求
2、作为一个前端,我们将问题聚焦于后面的两点浏览器显示HTML、浏览器发送请求获取嵌入在HTML中的资源(如图片、音频、视频、CSS、js等等)浏览器为了完成这两步骤到底发生了什么?
2.1首先我们先来了解下浏览器的组成
* 用户界面:定义了一些常用的浏览器组件,比如地址栏,返回、书签等等
* 数据持久化:指浏览器的cookie、local storage等组件
* 浏览器引擎:平台应用的相关接口,在用户界面和呈现引擎之间传送指令。
* 渲染引擎:处理HTML、CSS的解析与渲染
* JavaScript解释器:解析和执行JavaScript代码
* UI后端:指浏览器的的图形库等
* 网络:用于网络调用,比如HTTP请求
2.2接下来我们来看看浏览器渲染页面的主流程
当我们在浏览器的地址栏输入了url(用户界面),浏览器引擎通知渲染引擎调用网络API实现HTTP请求,当服务器返回一个响应后,渲染引擎开始工作
下面是在取得内容之后的基本流程:
解析html以构建dom树->构建render树->布局render树->绘制render树
渲染引擎开始解析html,并将标签转化为内容树中的dom节点。接着,它解析外部CSS文件及style标签中的样式信息。这些样式信息以及html中的可见性指令将被用来构建另一棵树——render树。
Render树由一些包含有颜色和大小等属性的矩形组成,它们将被按照正确的顺序显示到屏幕上。
Render树构建好了之后,将会执行布局过程,它将确定每个节点在屏幕上的确切坐标(layout\reflow)。再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。
3、DOM解析、CSS解析、渲染
3.1DOM解析
HTML的解析分为两个过程,词法解析和语法解析。词法解析就是将整个HTML文档拆分成一个一个标签,而语法解析就是列出这一个个标签之间的关系。下面就是HTML文档完成解析转成的DOM树:
<html>
<body>
<p>
Hello DOM
</p>
<div><img src=”example.png” /></div>
</body>
</html>
3.2CSS解析
将css文件解析为样式表对象。该对象包含css规则,该规则包含选择器和声明对象。
3.3渲染
3.3.1、计算CSS样式
计算CSS样式其实就是将CSS样式绑定到DOM节点上的过程, CSS匹配DOM Tree主要是从右到左解析CSS的选择器, CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,DOM树要小,CSS尽量用id和class选择器,千万不要过渡层叠下去,并且在最右边千万别写*通配符。
3.3.2、构建render树
构建render树就是将上面计算好的CSS样式和render Tree关联起来
3.3.3、layout(定位标签在页面中的位置)
将上面两步构建好的render Tree包含了位置、颜色、大小等信息,layout就是通过编译这些信息将DOM节点摆放到页面中对应的位置
3.3.4、paint (绘制元素)
确定好位置我们就要使用我们的UI组件来将形形色色的内容颜色具体的表现形式paint出来展示给大家了
值得注意的是在layout和paint的过程中有两个很重要的概念:
Reflow:字面意思是重新流程,我们需要去重新验证并计算Render Tree,这样就涉及到整个页面的修改,极好性能,所以我们在做性能优化的时候就是尽可能的让浏览器少Reflow
Repaint:字面意思是重新绘制,我们需要重画屏幕的一部分页面,但是不需要去重新验证并计算Render Tree,这样不会有那么大的性能损耗