输入url后到页面展示发生了什么?
第一步:找到这个url域名的服务器ip
1.1、浏览器会对url进行检查
完整的URL:协议、网络地址、资源路径、文件名、动态参数
首先是判断协议,协议的主要目的是告知浏览器如何处理打开的文件,然后对网络地址进行处理,如果不是IP地址而是域名,这时候就会通过DNS(域名系统)将该地址解析成IP地址。
1.2、DNS解析的两种方法是递归查询、迭代查询。
一般来说,会先查询本地的hosts文件是否配置了ip地址,然后再查看本地DNS解析器缓存,然后再到本地DNS服务器,如果没有包含在本地配置资源中,这时候就会用到递归查询/迭代查询
首先了解一下递归和迭代的差别,假如你想知道你女神的联系方式,然后你去找你的好兄弟(下面叫做A),他就相当于本地DNS服务器,他就开始帮你去找,刚好他的B朋友知道,然后从B那里拿到了号码给你,这就是递归。DNS客户-A-B-A
假如B不知道,但是他说C知道,这样A就去找C,C又说自己不知道,但是D知道,所以就去找D要到了好吗,这就是迭代,DNS客户-A-B-A ——A-C-A ——A-D-A
所以一般主机向本地DNS服务器查询一般采用递归查询,本地DNS服务器向根DNS服务器查询采用迭代查询
所以前端的dns优化,可以在HTML页面头部写入DNS缓存地址
拿到IP 地址后进行第二步。
第二步:浏览器发送HTTP请求
应用层客户端向服务器端发送的HTTP请求包括:请求报头和请求主体两个部分,其中请求报头(request header)包含了至关重要的信息,包括请求的方法(GET / POST和不常用的PUT / DELETE以及更不常用的HEAD / OPTION / TRACE,一般的浏览器只能发起 GET 或者 POST 请求)、目标url、遵循的协议(HTTP / HTTPS / FTP…),返回的信息是否需要缓存,以及客户端是否发送Cookie等信息。需要注意的是,因为 HTTP 请求是纯文本格式的,所以在 TCP 的数据段中可以直接分析 HTTP 文本的。
2.1、传输层TCP传输报文(会问三次握手)
当HTTP请求准备好后,浏览器会在传输层发起一条到达服务器的 TCP 连接,位于传输层的TCP协议(“三次握手”)为传输报文提供可靠的字节流服务。它为了方便传输,将大块的数据分割成以报文段为单位的数据包进行管理,并为它们编号,方便服务器接收时能准确地还原报文信息。
2.2、网络层IP协议查询MAC地址
IP协议的作用是把TCP分割好的各种数据包封装到IP包里面传送给接收方。而要保证确实能传到接收方还需要接收方的MAC地址,也就是物理地址才可以。IP地址和MAC地址是一一对应的关系,一个网络设备的IP地址可以更换,但是MAC地址一般是固定不变的。ARP协议可以将IP地址解析成对应的MAC地址。当通信的双方不在同一个局域网时,需要多次中转才能到达最终的目标,在中转的过程中需要通过下一个中转站的MAC地址来搜索下一个中转目标。
2.3、数据到达数据链路层
在找到对方的MAC地址后,已被封装好的IP包再被封装到数据链路层的数据帧结构中,将数据发送到数据链路层传输,再通过物理层的比特流送出去。
第三步:服务器接受数据、响应请求并返回相应文件
3.1、服务器接受数据
接收端的服务器在链路层接收到数据包,再层层向上直到应用层。这过程中包括在传输层通过TCP协议将分段的数据包重新组成原来的HTTP请求报文
3.2、响应请求并返回相应文件
服务接收到客户端发送的HTTP请求后,服务器上的的 http 监听进程会得到这个请求,然后一般情况下会启动一个新的子进程去处理这个请求,同时父进程继续监听。
服务器把将请求处理完形成正文后,会加上一个响应头,封装成一个标准的 http 响应包,再通过 tcp ip 协议,送回到客户机浏览器、
第四步:浏览器开始处理数据信息并渲染页面
4.1、判断状态码
响应到达浏览器之后,浏览器首先会根据返回的响应报文里的一个重要信息——状态码,来做个判断。如果是 200 开头的,表示请求成功,直接进入渲染流程,如果是 300 开头的就要去相应头里面找 location 域,根据这个 location 的指引,进行跳转,这里跳转需要开启一个跳转计数器,是为了避免两个或者多个页面之间形成的循环的跳转,当跳转次数过多之后,浏览器会报错,同时停止。比如:301表示永久重定向,即请求的资源已经永久转移到新的位置。在返回301状态码的同时,响应报文也会附带重定向的url,客户端接收到后将http请求的url做相应的改变再重新发送。如果是 400 开头或者 500 开头的状态码,浏览器也会给出一个错误页面。比如:404 not found 就表示客户端请求的资源找不到
4.2、解码字符集
响应的正文本质上就是一个字节流,浏览器会去看响应头里面指定的 encoding 域,如果有了这个东西,那么就按照指定的 encoding 去解析字符,如果没有的话,那么浏览器会使用一些比较智能的方式,去猜测和判断这一坨字节流应该使用什么字符集去解码。
4.3、构建DOM树
构建 dom 树的过程中,如果遇到了由 script 标签包起来的 js 动态脚本代码,那么会把代码送到 js 引擎里面去跑,如果遇到了 style 标签包围起来的 css 代码,也会保存下来,用于稍后的渲染。如果遇到了 img 或 css 和 js等引用外部文件的标签,那么浏览器会根据指定的 url 再次发起一个新的 http 请求,去把这个文件拉取回来
4.4、构造 render 树
根据 dom 树和 css 样式表来构造 render 树了,这个才是真正的用于渲染到页面上的一个一个的矩形框的树,网页渲染是浏览器最复杂、最核心的功能,对于 render 树上每一个框,需要确定他的 x y 坐标,尺寸,边框,字体,形态,等等诸多方面的东西。
特别注意:下载页面,构建 dom 树,构建 render 树这三个步骤,实际上并不是严格的先后顺序的,为了加快速度,提高效率,让用户不要等那么久,现在一般都并行的往前推进的,现代的浏览器都是一边下载,下载到了一点数据就开始构建 dom 树,也一边开始构建 render 树,构建了一点就显示一点出来,这样用户看起来就不用等待那么久了。