一个网页的加载过程
一个经典的面试题:从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
对于这个问题,其实也并没有标准答案,简单点,可能几句话就能回答,复杂点,这个过程的每一个细节都可以长篇大论。每一名开发人员,随着其工作年限的增长,对这个过程都会有更深入的理解。作为一个新人,本人也是仅知道皮毛,在查阅各路大神的回答和总结之后,在此记录梳理一番。
首先来看一下大致流程:
- DNS 解析
- 建立 TCP 连接(三次握手)
- 发送 HTTP 请求
- 服务器处理请求并返回 HTTP 报文
- 浏览器解析渲染页面
- 关闭 TCP 连接(四次挥手)
1、DNS 解析
DNS 域名解析,即根据域名寻找服务器主机 IP。
DNS 解析是一个递归查询的过程:
- 浏览器 DNS 缓存。当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的 IP 地址。(谷歌浏览器查看自身 DNS 缓存:chrome://net-internals/#dns)
- 操作系统缓存。当浏览器缓存中无域名对应 IP 则会自动检查用户计算机系统 Hosts 文件 DNS 缓存是否有该域名对应 IP。(windows 中
ipconfig/displaydns
来查看 DNS 缓存内容,ipconfig/flushdns
来清空 DNS 缓存内容,linx 系统缓存主要存在/etc/hosts
) - 路由器缓存。当浏览器及系统缓存中均无域名对应 IP 则进入路由器缓存中检查,以上三步均为客服端的 DNS 缓存。
- ISP(互联网服务提供商)DNS 缓存。当在用户客服端查找不到域名对应 IP 地址,则将进入 ISP DNS 缓存中进行查询。比如你用的是电信的网络,则会进入电信的 DNS 缓存服务器中进行查找。
- 根域名服务器。当以上均未完成,则进入根服务器进行查询。全球仅有 13 台根域名服务器,1 个主根域名服务器,其余 12 为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器 IP 告诉本地 DNS 服务器。
- 顶级域名服务器。顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的 IP 地址告诉本地 DNS 服务器。
- 主域名服务器。主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录。
其实真实的互联网世界背后存在成千上百台服务器,大型的网站甚至更多。但是在用户的眼中,它需要的只是处理他的请求,哪台机器处理请求并不重要。DNS 可以返回一个合适的机器的 IP 给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是 DNS 负载均衡,又叫做 DNS 重定向。大家耳熟能详的 CDN(Content Delivery Network)就是利用 DNS 的重定向技术,DNS 服务器会返回一个跟用户最接近的点的 IP 地址给用户,CDN 节点的服务器负责响应用户的请求,提供所需的内容。
2、建立 TCP 连接(三次握手)
TCP 位于传输层,提供可靠的字节流服务,将大块数据分割成以报文段为单位的数据包进行管理。
浏览器根据上一步获取到的 IP 地址向服务器发起 TCP 连接,进行 TCP 三次握手:
- 客户端首先发送一个带
SYN
标志的数据包给对方(我能和你建立连接吗?); - 服务器收到后,返回一个带有
SYN/ACK
标志的数据包以示传达确认信息(当然可以,收到请回复); - 最后,客户端再回传一个带
ACK
标志的数据包,完成三次握手,客户端与服务器开始传送数据(收到了)。
3、发起 HTTP 请求
HTTP 请求的过程就是构建 HTTP 请求报文,请求报文会被 TCP 协议分割成报文段,然后发送到服务器指定端口。 HTTP 请求报文由两部分组成: 请求头、请求体。请求头又包括请求行、实体头、头部结束标志三部分;其中请求行是请求方法(GET、POST、OPTION、PUT…)、请求地址、协议版本(HTTP/1.0 HTTP/1.1)的声明,实体头是各种首部字段的值;请求体即传送的数据。
详细请查看:图解 HTTP 学习笔记(四):HTTP 报文。
4、服务器处理请求并返回 HTTP 报文
服务器对应端口接收到 HTTP 请求报文后,相应的服务端程序开始对请求作出一系列处理,并组织响应数据,通过 HTTP 协议构建响应报文,响应报文同样由两部分组成:响应头、响应体。响应头中包含各种状态码(200、403…)表示响应状态。
5、浏览器解析渲染页面
浏览器在收到 HTML、CSS、JS 文件后,它是如何把页面呈现到屏幕上的? 下图对应的就是 WebKit 渲染的过程。
浏览器是一个边解析边渲染的过程。首先浏览器解析 HTML 文件构建 DOM 树,然后解析 CSS 文件构建 渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和 repain(重绘)。DOM 节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为 relow;当盒模型的位置、大小以及其他属性,如颜色、字体、等确定下来之后,浏览器便开始绘制内容,这个过程称为 repain。页面在首次加载时必然会经历 reflow 和 repain。reflow 和 repain 过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少 reflow 和 repain。
JS 的解析是由浏览器中的 JS 解析引擎完成的。浏览器在解析过程中,如果遇到请求外部资源时,如图像,iconfont,JS 等,浏览器将请求并加载该资源。请求过程是异步的,并不会影响 HTML 文档进行加载,但是当文档加载过程中遇到 JS 文件,HTML 文档会挂起渲染过程,不仅要等到文档中 JS 文件加载完毕还要等待解析执行完毕,才会继续 HTML 的渲染过程。原因是因为 JS 有可能修改 DOM 结构,这就意味着 JS 执行完成前,后续所有资源的下载是没有必要的,这就是 JS 阻塞后续资源下载的根本原因。CSS 文件的加载不影响 JS 文件的加载,但是却影响 JS 文件的执行。JS 代码执行前浏览器必须保证 CSS 文件已经下载并加载完毕。
6、关闭 TCP 连接(四次挥手)
通过四次挥手关闭 TCP 连接。
- 主机向服务器发送一个断开连接的请求(我要走了);
- 服务器接到请求后发送确认收到请求的信号(知道了);
- 服务器向主机发送断开通知(我也要走了);
- 主机接到断开通知后断开连接并反馈一个确认信号(好的),服务器收到确认信号后断开连接;
7、后记
上面部分主要介绍了一次完整的请求对应的过程,了解该过程有助于对 Web 开发的整体把控以及优化。
如何尽快的加载资源?答案就是能不从网络中加载的资源就不从网络中加载,合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即 DNS 优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。当资源到达浏览器之后,浏览器开始进行解析渲染,浏览器中最耗时的部分就是 reflow,所以围绕这一部分就是考虑如何减少 reflow 的次数。
参考
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章