从输入URL到页面展示过程中发生了什么???
浏览器进程、渲染进程和网络进程的主要职责
- 浏览器进程主要负责用户交互、子进程管理和文件储存等功能。
- 网络进程是面向渲染进程和浏览器进程等提供网络下载功能。
- 渲染进程的主要职责是把从网络下载的HTML、JavaScript、CSS、图片等资源解析为可以显示和交互的页面。因为渲染进程所有的内容都是通过网络获取的,会存在一些恶意代码利用浏览器漏洞对系统进行攻击,所以运行在渲染进程里面的代码是不被信任的。这也是为什么Chrome会让渲染进程运行在安全沙箱里,就是为了保证系统的安全
用户输入,合成URL
用户输入URL,浏览器根据用户输入的信息判断是搜索内容还是请求的URL:
- 如果是
搜索内容
,将搜索内容和默认搜索引擎合成新的URL; - 如果是
URL
,判断是否符合URL的规则,浏览器就根据URL协议,在这段内容上加上协议合成合法的URL
URL请求过程
然后进入页面资源请求过程。这个时候浏览器进程会通过进程间通信(IPC)把URL请求发送至网络进程,网络进程接收到URL请求后,会在这里发起真正的URL请求流程。
首先,网络进程会查找本地缓存是否缓存了该资源。(浏览器缓存中查找
)
-
如果有缓存资源(强制缓存),就是之前已经访问过这个网页,浏览器会缓存访问过网站的网页,当再次访问这个 URL 地址的时候,如果网页没有更新,就不会再次下载网页,那么直接返回缓存的资源给浏览器进程;
-
如果在缓存中没有查找到资源(浏览器缓存中没有/已过期,需进行协商缓存),那么直接进入网络请求流程。这请求前的第一步是要进行DNS解析,以获取请求域名的服务器IP地址。如果请求协议是HTTPS,那么还需要建立TLS连接。
DNS域名解析
在客户端输入 URL 后,会有一个递归查找的过程,这个过程中任何一步找到了都会结束查找流程。
-
浏览器会首先查看本地硬盘的 hosts 文件,看看其中有没有和这个域名对应的规则,如果有的话就直接使用 hosts 文件里面的 ip 地址。
-
如果在本地的 hosts 文件没有能够找到对应的 ip 地址,浏览器会发出一个 DNS请求到本地DNS服务器 。本地DNS服务器一般都是你的网络接入服务器商提供,比如中国电信,中国移动。
-
查询你输入的网址的DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果,此过程是递归的方式进行查询。如果没有,本地DNS服务器还要向DNS根服务器进行查询。( 客户端和浏览器,本地DNS之前的查询方式是递归查询 )
-
根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器,你可以到域服务器上去继续查询,并给出域服务器的地址。这种过程是迭代的过程。( 本地DNS服务器与根域及其子域之间的查询方式是迭代查询 )
-
本地DNS服务器继续向域服务器发出请求,在这个例子中,请求的对象是.com域服务器。.com域服务器收到请求之后,也不会直接返回域名和IP地址的对应关系,而是告诉本地DNS服务器,你的域名的解析服务器的地址。
-
最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。
建立TCP连接,三次握手
SYN:同步连接序号,TCP SYN报文就是把这个标志设置为1,来请求建立连接;
ACK:请求/应答状态。0为请求,1为应答;
FIN:结束连线。如果FIN为0是结束连线请求,FIN为1表示结束连线;
第一次握手:建立连接。 客户端发送连接请求报文段,将 SYN标志位 置为1,Sequence Number为x;然后客户端进入SYN_SENT状态,等待服务器确认。( SYN=1,seq=x )
第二次握手:服务器收到SYN报文段。 服务器收到客户端的SYN报文段,对这个报文段进行确认,设置Acknowledgement Number 为 x+1(Sequence Number + 1),ACK位置为1;同时,自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(SYN+ACK报文段),一并发送给客户端,服务器端进入SYN_RCVD状态。(SYN=1,ACK=1,seq=y,ACKnum=x+1 )
第三次握手:客户端收到服务器的SYN+ACK报文段。 然后将Acknowledgement Number设置为y+1(Sequence Number + 1),向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。( ACK=1,ACKnum=y+1 )
- 客户端向服务器端发送SYN + Seq 是连接请求
- 服务器返回新的 SYN + Seq 是服务器端向客户端发送连接请求,发送 ACK + Acknum 是响应客户端发来的连接请求
- 客户端向服务器再发送ACK + ACKnum 是客户端响应服务器端发来的连接请求
发送HTTP请求,服务器处理请求,返回响应结果
tcp连接建立后,浏览器就可以利用HTTP/HTTPS协议向服务器发送请求,浏览器端会构建请求行、请求头等信息,把和这个域名相关的Cookie等数据附加到请求头中,然后向服务器发送构建的请求信息。服务器接收到请求,就解析请求头,如果头部有缓存相关信息如if-none-match与if-modified-since,就验证缓存是否有效。若有效则返回状态码304,无效则重新返回资源,状态码为200。
关闭TCP连接,四次挥手
浏览器接收HTTP响应,然后根据情况选择关闭TCP连接还是保留重用,如果要关闭TCP连接的话要经过四次挥手。 客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行
close() 操作即可产生挥手操作。
第一次挥手 :主机1( 可以是客户端,也可以是服务器端 ),向主机2发送一个FIN报文段,FIN标志位 置为1,设置Sequence Number 为 x ;这个时候,主机1进入FIN_WAIT_1状态
;这表示主机1没有数据要发送给主机2了,但是这个时候仍然可以接收数据;( FIN=1,seq=x )
第二次挥手 :主机2收到主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledge Number为x+1( Sequence Number加1 );发送完毕后,主机2进入 CLOSE_WAIT 状态
,主机1进入FIN_WAIT_2状态
,主机2告诉主机1,我"同意"你的关闭请求。( ACK=1,ACKnum=x+1 )
第三次挥手 :主机2向主机1发送FIN报文段,FIN标志位 置为1,设置Sequence Number 为 y,请求关闭连接,同时主机2进入LAST_ACK状态
。( FIN=1,seq=y )
第四次挥手 :主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,Acknowledge Number为x+1( Sequence Number加1 ),然后主机1进入TIME_WAIT状态
;服务器端接收到这个确认包之后,关闭连接,进入 CLOSED
状态。此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了,进入 CLOSED
状态( ACK=1,ACKnum=y+1 )
浏览器渲染
1. 处理 HTML
并构建 DOM
树
浏览器获取到 HTML 内容后,就开始从上到下解析 HTML 的元素,解析出来的结果会成为一颗dom树,作为下个阶段渲染树状图的输入,还有成为网页和脚本的交互界面。 <head>
元素内容会先被解析,这个时候浏览器还没开始渲染页面
我们看到<head>
元素里有用于描述页面元数据的<meta>
元素,还有一些<link>
元素涉及外部资源(如图片、CSS 样式
等),此时浏览器会去获取这些外部资源。除此之外,我们还能看到<head>
元素中还包含着不少的<script>
元素,这些<script>
元素通过src
属性指向外部资源。
当浏览器解析到这里时,会暂停解析并下载 JavaScript 脚本。当 JavaScript 脚本下载完成后,浏览器的控制权转交给 JavaScript 引擎。当脚本执行完成后,控制权会交回给渲染引擎,渲染引擎继续往下解析 HTML
页面。
此时<body>
元素内容开始被解析,浏览器开始渲染页面
2. 处理 CSS
构建 CSSOM
树
3. 将 DOM
与 CSSOM
合并成一个渲染树(render tree)
4. 根据渲染树来布局,计算每个节点的位置
布局(layout
):定位坐标和大小,是否换行,各种position
, overflow
, z-index
属性
5. 调用 GPU
绘制,合成图层,显示在屏幕上
将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting