浏览器 - 页面渲染过程
一、浏览器中输入Url之后,浏览器全过程
1、DNS解析
输入Url之后,首先浏览器会先进行DNS域名解析。
(1)操作系统会先检查本地的 hosts 文件时候有这个网址的映射关系,如果有那这就先调用这个IP地址的映射,完成域名的解析。
(2)本地 hosts 中不存在这个域名的映射的话,那么会查询 DNS解析器的缓存,如果存在缓存,则完成域名的解析。
(3)如果 hosts 和 缓存 中都没有的话,那么 DNS 会依次向 跟域名服务器、顶级域名服务器、权威域名服务器 发起查询请求,直至找到一个或一组IP地址,并返回给浏览器,完成域名的解析。( DNS查询请求方式是递归或者迭代,从客户端到本地DNS
服务器是属于递归查询,而DNS服务器之间就是的交互查询就是迭代查询。)
2、TCP/IP 连接
3、三次握手
这一步骤的目的是为了TCP连接。
第一次握手 客户端向服务端发送SYN报文并设置发送序号为X,客户端进入 SYN_SENT 状态,等待服务器回应。
第二次握手 服务端收到 SYN 报文之后,服务端需要确定客户端的 syn(ack = X + 1),因此服务端会发送 SYN = Y 来让客户端确认。 服务端发送 SYN、ACK报文,并且服务端进入 SYN_RECV 状态
第三次握手 客户端接收到服务端的 SYN+ACK 报文之后,向服务端发送确认包 ACK( ack = Y + 1 )。此包发送完毕后,客户端和服务端进入 ESTABLISHED (TCP连接成功),完成三次握手。
三次握手完成之后,TCP连接成功之后就可以进行HTTP请求了。
4、四次挥手
TCP 是一个全双工协议,必须单独拆除每一条信道。4次挥手的目的是终止数据传输,并回收资源。
客户端 发送一个 FIN,用来关闭客户到服务器的数据传送。
服务端 收到这个 FIN,服务端发回一个 ACK,确认序号 为收到的 序号加1。和SYN一样,一个FIN将占用一个序号。
服务端 关闭客户端的连接,发送 一个 FIN 给 客户端。
客户端 发回 ACK 报文确认,并将确认序号设置为收到 序号加1。
5、页面渲染
浏览器拿到响应文本之后,接下来就是进行浏览器的渲染机制。
二、页面渲染过程
1、浏览器工作流程
* HTML、SVG、XHTML 这三类文件被解析生成 DOM Tree。
* CSS 文件 解析成 CSSOM Tree (CSS规则树)
* JavaScript 会调用 DOM API 和 CSS API,生成 DOM Tree 和 CSSOM Tree。
* DOM Tree 和 CSS Tree 一起构成了 Render Tree (渲染树)。
2、浏览器渲染
页面的渲染顺序:
* 浏览器获取到文件之后,首先浏览器会先 解析 HTML, 如果遇到 外链CSS,浏览器会先 一边下载 CSS文件 一边 解析HTML
* CSS文件 下载完成之后,会继续解析CSS文件,生成CSS Rule Tree,不会影响HTML的解析
* 如果遇到 <script> 标签,一旦发现 JavaScript 的引用,就会立即下载 javascript 脚本并执行,同时阻断文档的解析。等脚本执行完成之后,继续进行HTML文档的解析
* 当 DOM 和 CSS Rule Tree 已经生成完毕后,构造 Render Tree
* 调用系统渲染页面
HTML 会等到头部的css、js文件解析完成之后在继续执行。解决这个问题的三种方式:
1、将脚本文件都放在网页尾部加载
js放在body的最后面,可以避免资源阻塞,同时使静态的html页面迅速显示。
在DOM结构生成之前就调用DOM,JavaScript会报错,如果脚本都在网页尾部加载,就不存在这个问题,因为这时DOM肯定已经生成了。
2、async="true"
async="true"属性 不会依赖于任何 js 和 css 的执行,此 js下载完成后 立刻执行,不保证按照书写的顺序执行。
async相当于告诉浏览器,这个script文件不会对 DOM和样式 进行操作,所以可以同时执行
async
属性可以保证脚本下载的同时,浏览器继续渲染。
3、defer="true"
defer="true"属性 会并行加载js,到页面 全部加载完成后 才会执行,会按顺序执行。
defer
属性的作用是,告诉浏览器,等到DOM加载完成后,再执行指定脚本。