# 前言
我们常常都知道从 url 到页面渲染会包括如下流程:
- dns 域名解析,得到对应的 ip 地址
- 根据这个 ip,找到对应的服务器连接(三次握手)
- 建立 tcp 连接后发起 http 请求
- 服务器响应 http 请求,浏览器得到 html 代码
- 浏览器解析 html 代码,并请求 html 中的资源(如 js,css,图片等)
- 服务器渲染页面
- 服务器关闭 tcp 连接(四次挥手)。
虽然这些步骤是大体程序步骤,但这样会显得知其然而不知其所有然。
接下来我将会对上述步骤阐述更多个人的深度理解。
# 一、dns 如何查找对应的 ip 地址的?
首先会查找自身缓存中是否存在该 dns 解析后的 ip 地址,若无,便会去其操作系统的 host 文件中去查找对应的字段,若还未命中则,下述操作便会被执行。
若 dns 域名对应的 ip 未存到缓存之中,其查找过程如下:
上述过程中,从本地域名到最终的 google.com 域名为一个迭代查询的过程。但在其迭代查询过程之前,会有一个递归查询 -- 即上述提到的本地 host 文件查询,查找是否存在当前域名的 ip 地址。
# 二、浏览器是如何进行渲染的?
浏览器进行渲染时,会调用 render 进程(renderer process),其包含如下相关线程:
- 主线程 Main thread
- 工作线程 Worker thread
- 排版线程 Compositor thread
- 光栅线程 Raster thread
其工作流程如下:
简而言之, html文件->dom树
, css->cssdom
树,二者结合成 render tree
, 而后,render tree 根据计算渲染对象信息,计算出每个渲染对象的位置和尺寸,进而形成 layout tree
除此之外,浏览器还将记录下不同元素的绘制顺序,以便正确的绘制整个页面。而这一过程,浏览器将会通过遍历上述的 layout tree 来实现,生成的绘制顺序框图,我们称之为 Draw Rect
。
而后涉及到的知识便会略显生涩,如,我们在拿到对应的布局树(layout tree)和绘制顺序(Paint Records)之后,我们将其两个步骤进行复合,得到对应的 LayerTree (图层树),并对其栅格化处理,交由 GPU 进程进行处理,而后 GPU 通过 IPC协议
将相关消息发送到浏览器进程,进行页面渲染。
总结:生成各种树,包括 dom tree, css tree, layout tree, layer true, render tree,这些是 渲染器进程
中的 GUI渲染线程
做的事。其中 js 脚本的解析执行是同进程下的 js 引擎线程来做的,也就是大名鼎鼎的 V8引擎
。至于定时器回调,是 定时器线程
来计数,计数完毕会把回调推入事件触发线程维护的 任务队列
,当 js 线程空闲并且此线程维护的微任务队列无事件,才会去任务队列拿 宏任务
执行处理。)