# 这是老经典的题了:浏览器输入 url 后发生了什么事

image-20211112103143396

# 大致流程

  1. 浏览器进程发出URL 请求给网络进程
  2. 网络进程接收到 URL 请求后,发起网络请求,然后服务器返回 HTTP 数据到网络进程,网络进程解析 HTTP 响应头数据,并将其转发给浏览器进程
  3. 浏览器进程接收到网络进程的响应头数据后,发送 CommitNavigation 消息到渲染进程,发送 CommitNavigation 时会携带响应头等基本信息
  4. 渲染进程接收到 CommitNavigation 消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道
  5. 最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程,说我已经准备好接收和解析页面数据
  6. 最后浏览器进程更新页面状态

# 分析每个流程

# 用户输入 URL

浏览器的地址栏会判断所输入的内容是搜索还是网址

  • 如果是搜索内容,就将搜索内容+默认搜索引擎合成新的 URL;

  • 如果用户输入的内容符合 URL 规则,浏览器就会根据 URL 协议,在这段内容上加上协议合成合法的 URL,比如输入www.baidu.com 地址栏会根据规则,把这段内容加上协议,合成完整的 URL,如https://www.baidu.com

补充:

  • 用户输入完内容,按下回车键,浏览器导航栏显示loading 状态,但是页面还是呈现前一个页面,这是因为新页面的响应数据还没有获得

  • 这里面有个beforeunload 事件,该事件允许页面退出之前执行一些数据的清理操作,还可以询问用户是否要离开当前页面,比如当前页面有未提交的表单,用户可以通过 beforeunload 事件来取消导航,让浏览器不在进行后续工作。

# URL 请求过程

  • 浏览器进程将构建请求行数据,进行进程间通信(IPC)将 URL 请求发送给网络进程,类似于下面这个:
GET /index.html HTTP1.1
1
  • 网络进程获取到 URL,先去本地缓存(也叫浏览器缓存,浏览器缓存是在磁盘中的)中查找是否有缓存文件(hosts 文件优先级比本地缓存高,先查找 hosts 文件再看本地缓存),如果有,拦截请求,直接 200 返回;否则,进入网络请求过程(具体看浏览器缓存

  • 网络进程向本地 DNS 服务器请求该域名对应的IP 和端口号,如果之前DNS 数据缓存服务缓存过当前域名信息,就会直接返回缓存信息;否则,发起请求获取根据域名解析出来的 IP 和端口号,如果没有端口号,http 默认 80https 默认 443。如果是 https 请求,还需要建立TLS 连接。(具体看DNS 解析原理

  • 在进程 TCP 连接的过程中,Chrome 有个机制,同一个域名下最多只能建立6 个 TCP 连接,如果在同一个域名下有 10 个请求发生,那么其中 4 个请求会进入等待转台,直至进行中的请求完成。如果请求个数小于 6,会直接建立 TCP 连接。

  • TCP 三次握手建立连接,http 请求加上 TCP 头部——包括源端口号目的程序端口号用于校验数据完整性的序号,向下传输。

  • 网络层在数据包上加上 IP 头部——包括源 IP 地址目的 IP 地址,继续向下传输到底层

  • 底层通过物理网络传输给目的服务器主机,紧接着目的服务器主机网络层接收到数据包解析出 IP 头部,识别出数据部分,将解开的数据包向上传输到传输层。

  • 目的服务器主机传输层获取到数据包,解析出 TCP 头部识别端口,将解开的数据包向上传输到应用层

  • 应用层 HTTP解析请求头和请求体

    • 如果需要重定向,HTTP 直接返回 HTTP 响应数据的状态 code301 或者 302,同时在请求头的 Location 字段中附上重定向地址,浏览器会根据 code 和 Location 进行重定向操作;
    • 如果不是重定向,首先服务器会根据请求头中的 If-None-Match 的值来判断请求的资源是否被更新
    • 如果没有更新,就返回 304 状态码,相当于告诉浏览器之前的缓存还可以使用,就不返回新数据了;
    • 否则,返回新数据,200 的状态码,并且如果想要浏览器缓存数据的话,就在相应头中加入字段:
      Cache-Control:Max-age=2000
      
      1
  • 响应数据又顺着应用层——传输层——网络层——网络层——传输层——应用层的顺序返回到网络进程

  • 数据传输完成,TCP 四次挥手断开连接。如果,浏览器或者服务器在 HTTP 头部加上如下信息,TCP 就一直保持连接。保持 TCP 连接可以省下下次需要建立连接的时间,提高资源加载速度

    	```http
    	Connection:Keep-Alive
    	```
    
  • 网络进程将获取到的数据包进行解析,根据响应头中的 Content-type 来判断响应数据的类型,如果是字节流类型,就将该请求交给下载管理器;如果是text/html 类型,就通知浏览器进程获取文档准备渲染

image-20211112103153704

image-20211112103158988

  • 从返回的响应头信息来看,其 Content-Type 的值是 application/octet-stream,显示数据是字节流类型的,通常情况下,浏览器会按照下载类型来处理该请求。需要注意的是,如果服务器配置 Content-Type 不正确,比如将 text/html 类型配置成 application/octet-stream 类型,那么浏览器可能会曲解文件内容,比如会将一个本来是用来展示的页面,变成了一个下载文件。

  • 浏览器进程获取到通知,根据当前页面 B 是否是从页面 A 打开的并且和页面 A 是否是同一个站点(根域名和协议一样就被认为是同一个站点),如果满足上述条件,就复用之前网页的进程,否则,新创建一个单独的渲染进程。

  • 浏览器会发出“提交文档”的消息给渲染进程,渲染进程收到消息后,会和网络进程建立传输数据的“管道”,文档数据传输完成后,渲染进程会返回“确认提交”的消息给浏览器进程。

  • 浏览器收到“确认提交”的消息后,会更新浏览器的页面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新 web 页面,此时的 web 页面是空白页。这也解释了为什么在浏览器的地址栏里面输入了一个地址后,之前的页面没有立马消失,而是要加载一会儿才会更新页面。

image-20211112103204834

  • 渲染进程对文档进行页面解析和子资源加载,HTML 通过 HTML 解析器转成DOM Tree(二叉树类似结构的东西),CSS 按照 CSS 规则和 CSS 解释器转成CSSOM Tree,两个 tree 结合,形成render tree(不包含 HTML 的具体元素和元素要画的具体位置),通过 Layout 可以计算出每个元素具体的宽高颜色位置,结合起来,开始绘制,最后显示在屏幕中新页面显示出来。(具体看浏览器渲染原理

# 参考

「浏览器工作原理」写给女友的秘籍-浏览器组成&网络请求篇(1.2W 字) (opens new window)

从输入 URL 到页面加载发生了什么 (opens new window)

导航流程:从输入 URL 到页面展示,这中间发生了什么? (opens new window)

浏览器的工作原理:现代网络浏览器幕后揭秘 (opens new window)

最近更新: 4 小时前