大家好,我是小杜杜,今天聊聊一个老生常谈的话题:浏览器的渲染过程,在面试的过程中,这个问题也是常考题,通常面试官会问:从输入一个 url 地址到浏览器完成渲染的整个过程发生了什么?
渲染的过程实际上非常复杂,我们需要了解并熟知其过程即可
发生的过程
当浏览器地址栏输入 URL 并回车的过程依次是(建议熟记~):
- 浏览器查找当前 URL 是否存在缓存,并比较缓存是否过期
- DNS 解析 URL 对应的 IP
- 根据 IP 建立 TCP 链接(三次握手)
- 发送 http 请求
- 服务器处理请求,浏览器接受 HTTP 响应
- 浏览器解析并渲染页面
- 关闭 TCP 链接(四次握手)
查找缓存
浏览器首先会去查找缓存,就好像你要去一个地方,首先要想这个地方去过没有,如果去过直接过去,没去过则按照导航一步一步过去,那么浏览器也是一样的。
浏览器先查看浏览器缓存
=> 系统缓存
=> 路由缓存
中是否有该地址页面,如果有则直接显示页面内容,反之则进行下一步。
- 浏览器缓存:浏览器会记录 DNS 一段时间,因此,只是第一个地方解析 DNS 请求;
- 系统缓存:如果在浏览器缓存中不包含这个记录,则会使系统调用操作系统,获取操作系统的记录(保存最近的 DNS 查询缓存);
- 路由器缓存:如果上述两个步骤均不能成功获取 DNS 记录,继续搜索路由器缓存;
最后,三个缓存都为寻找到,则继续想 ISP 搜索
DNS 解析
DNS 解析一般指域名解析,是把域名所指向网站空间 IP,也就是数字地址,而域名解析的主要作用就是便于记忆。
那么为什么需要解析呢?
因为在网络通信中,大部分是机遇 TCP/IP
的,而 TCP/IP
是基于 IP
地址的,所以计算机在网络上只能识别IP 地址(如:202.97.111.101),而不能识别域名
TCP 链接
之后会根据IP
进行TCP
链接,通过 IP 和默认的 80 端口,和服务器简历 TCP 链接
具体如何链接可以看看这篇文章 TCP 三次握手和四次挥手深入实践
浏览器是如何解析并渲染页面
我们知道执行 JS 有一个 JS 引擎,那么执行渲染也有一个渲染引擎。同样,渲染引擎在不同的浏览器中也不是都相同的。
比如在 Firefox 中叫做 Gecko,在 Chrome 和 Safari 中都是基于 WebKit 开发的。
过程图:
我们从图中可以看到
- 首先将 HTML 通过 HTMl parser 转化为
DOM tree
, 同时 css 通过 ccs 规则和 css 解析器转化为CSSDOM tree
- 然后将两者进行合成,形成最终的
render tree
(注意:此时并不知道 html 的具体内容,也不知道具体位置是什么) - 然后通过
layout
就可以精确计算到要显示的这些 dom 真正的宽高,位置颜色,最后开始paint
,画图,把内容呈现出来
如何将 HTML 转化为 DOM 树
我们知道,我们写代码的时候会分为 HTML、CSS、JS 文件,也就是字符串,但计算机硬件是不理解这些字符串的,实际上,在网络传输中的内容实际上都是 0 和 1 的字节数据
。
当浏览器拿到这些字节数据的时候,换转化成对应的字符串,也就是我们写的代码。
之后浏览器会将这些字符串通过此法分析转化为标记(token)
,这一过程叫做标记化
那么为什么要进行标记呢?原因是最终会把代码拆分成一块一块的,并且给这些内容打上标记,便于理解这块代码是什么意思。
如:
当标记结束后,紧接着会转化为 Node,然后这些 Node 会形成一个 DOM 树
总结下所进行的过程:字节数据 => 字符串 => Token => Node => DOM
如何将 CSS 转化为 CSSDOM 树
跟 HTML 转化为 DOM 树的过程非常类似,其过程为:字节数据 => 字符串 => Token => Node => CSSDOM
注意这一过程浏览器会确定下每一个节点的样式到底是什么,并且这一过程其实是很消耗资源的。
举个简单的例子:
<div>
<p> <span> </span> </p>
</div>
//渲染样式,分别对 span 进行渲染
// 第一种
span {
color: red;
}
//第二种
div > p > span {
color: red;
}
- 对于第一种而言,浏览器只要找到对应的 span 标签即可
- 对于第二种而言,浏览器需要找到所有的 span 标签,再找到 span 标签的 p 标签,再找到之上的 div 标签,然后给符合这种规则的标签设置颜色,这样的过程就会变得很复杂
如何渲染为最终的 render tree
当我门拿到 DOM Tree 和 CSSDOM Tree 时,要将两棵树进行结合,这一过程并不是简简单单的将两者合并。
需要注意的是
- Render Tree 只包含需要显示的节点和这些节点的样式信息,比如样式为
display:none
的,并不再Render Tree
中展示 - 当浏览器生成渲染树以后,就会根据渲染树来进行布局(也可以叫做
回流
),然后调用 GPU 绘制,合成图层,显示在屏幕上。(这一部分的内容过于底层,还涉及到硬件相关的知识)
End
致此,有关浏览器渲染就已经完成了,相信各位小伙伴已经了解其过程了,喜欢的点个赞 👍🏻 支持下吧(●  ̄(エ) ̄ ●)