浏览器从输入 URL 到页面呈现都发生了什么?

83 阅读6分钟

整个过程涉及内容较多:

1. 浏览器接受URL开启网络请求线程(涉及到:浏览器机制,线程与进程等)

2. 开启网络线程到发出一个完整的http请求(涉及到:DNS查询,TCP/IP请求,5层网络协议等)

3. 从服务器接收到请求到对应后台接收到请求(涉及到:负载均衡,安全拦截,后台内部处理等)

4. 后台与前台的http交互(涉及到:http头,响应码,报文结构,cookie等)

5. 缓存问题(涉及到:http强缓存与协商缓存,缓存头,etag,expired,cache-control等)

6. 浏览器接受到http数据包后的解析流程(涉及到html词法分析,解析成DOM树,解析CSS生成CSSOM树,合并生成render渲染树。然后layout布局,painting渲染,复合图层合成,GPU绘制,外链处理等)

7. css可视化模型(涉及到:元素渲染规则,如:包含块,控制框,BFC,IFC等)

8. JS引擎解析过程(涉及到:JS解析阶段,预处理阶段,执行阶段生成执行上下文,VO(全局对象),作用域链,回收机制等)

主要过程如下:

(1) 解析 URL 分析传输协议和请求资源路径。检查 URL 中的 协议主机名 是否合法 ?是否出现非法字符?

(2) 缓存判断 浏览器会判断所请求的资源是否在缓存里?

- 如果请求的资源在缓存里并且没有失效,那么就直接使用,
- 否则向服务器发起新的请求。

(3) DNS解析【域名解析,即域名 ——> IP地址】

- 判断本地是否有该域名对应 IP 地址的缓存:
    - 有:使用
    - 没有:向本地 DNS 发起请求

- 本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后,再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户。

(4)获取 MAC 地址【当浏览器得到 IP 地址后,数据传输还需要知道目的主机 MAC 地址】:

-  应用层 ----> 传输层 ,TCP 指定源端口号、目的端口号。
-  传输层 -----> 网络层,网络层把获取的 IP 地址作为目的地址。
-  网络层 -----> 数据链路层,数据链路层把本机的 MAC 地址作为源 MAC 地址,目的 MAC 地址需要分情况处理:
    - 通过将 IP 地址与本机的子网掩码相与,可以判断是否与请求主机在同一个子网里?
        - 如果在同一个子网里,可以使用 **APR 协议** 获取到目的主机的 MAC 地址
        - 如果不在一个子网里,那么请求应该转发给网关,由它代为转发,此时同样可以通过 ARP 协议来获取网关的 MAC 地址,此时目的主机的 MAC 地址应该为网关的地址。

(5) TCP 三次握手

- 客户端向服务器发送一个 SYN = 1,连接请求报文段和一个随机序号
- 服务端接收到请求后向服务器端发送一个 SYN=1 ,ACK=1 报文段,确认连接请求
- 客户端接收服务器的确认应答后,进入连接建立的状态,同时向服务器也发送一个ACK = 1 确认报文段

(6) HTTPS 下的 TLS 四次握手

- 客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法
- 服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书CA
- 客户端收到后,首先检查数字证书是否有效,如果有效,则再生成一个随机数,并**使用证书中的公钥对随机数加密,然后发送给服务器端**
- 服务器端接收后,使用自己的私钥对数据解密,同时向客户端发送一个前面所有内容的 hash 值供客户端检验

【这个时候双方都有了三个随机数,按照之前所约定的加密方法,使用这三个随机数生成一把秘钥,以后双方通信前,就使用这个秘钥对数据进行加密后再传输。】

(7) 客户端发起请求,服务器响应

(8) 客户端收到数据,进行浏览器渲染

- 解析 HTML ,并生成 DOM 树
- 在解析 HTML 过程中,(异步)加载外部资源(CSS、js 、图片...)
- 解析 CSS ,构建 CSSOM 树
- 【将 DOM 树和 CSSOM 树结合】构建渲染树【渲染树只包含需要显示的元素和对应的样式信息。】
- 布局计算【浏览器根据渲染树中每个元素的尺寸、位置和样式信息进行布局计算,确定每个元素在页面中的准确位置。】
- 绘制页面【浏览器使用布局计算得到的位置信息,将渲染树中的每个元素绘制到屏幕上,形成用户可见的网页。】
- 在渲染页面的过程中,遇到 JS 就解析执行,【可能会导致重新渲染】
- 渲染优化!!【使用缓存,延迟加载,提高性能】

(9) TCP四次握手终端连接

- 客户端认为数据发送完成,则它需要向服务端发送连接释放请求。
- 服务端收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明客户端到服务端的连接已经释放,不再接收客户端发的数据了。【客户端 --- > 服务器端已经断了】

【但是因为 TCP 连接是双向的,所以服务端仍旧可以发送数据给客户端。服务端如果此时还有没发完的数据会继续发送】

  • 服务器端确定没有数据要发给客户端的了,发送连接释放请求,然后服务端便进入 LAST-ACK 状态。
  • 客户端收到释放请求后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态

【该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入 CLOSED 状态。】