当用户输入了url后,浏览器做了些什么?

120 阅读7分钟

当用户输入了url后,浏览器做了些什么?

这是一道面试中出现频率非常高的题目,要想将其表达清除并不容易,我建议可以心中列出一套大概的表达逻辑,然后根据这个表达逻辑,认真准确地表达好每一个细节!

大体上,我想将这个问题分为两个阶段,一是网络阶段,二是渲染阶段:

网络阶段

当我们输入“www.baidu.com”时:

首先在最开始,会查看当前浏览器中是否有强缓存的记录,如果有的话,可以直接获取强缓存的记录,如果没有的话,才会进入下面的过程

1.DNS解析(DNS:Domain Name System)

DNS解析是将域名转换为服务器IP地址的过程,分为本地缓存查询和递归查询两个阶段:

一、本地缓存查询(按顺序检查)

  1. 浏览器缓存:优先检查浏览器自身的DNS缓存记录

  2. 系统缓存:若未命中,则查询操作系统缓存

    • 同时检查hosts文件(Windows/Linux系统中手动配置的域名映射)
  3. 路由器缓存:继续查询局域网路由器的缓存记录

  4. ISP DNS缓存:最后查询互联网服务提供商(ISP)的DNS服务器缓存

二、递归查询流程(缓存未命中时)

当本地无缓存时,进行全球DNS层级查询:

  1. 根域名服务器查询(.)

    • 全球13组根服务器返回对应顶级域(TLD)服务器地址
    • 例:查询"www.baidu.com" → 返回.com顶级域服务器地址
  2. 顶级域名服务器查询(.com/.cn等)

    • 获取权威域名服务器(Authoritative DNS)地址
    • 接上例:.com服务器返回baidu.com域名的权威服务器地址
  3. 权威域名服务器查询

    • 最终获取域名对应的真实IP地址
    • 接上例:baidu.com权威服务器返回www.baidu.com的IP
  4. 结果返回与缓存

    • 本地DNS服务器将IP返回客户端
    • 各级缓存该记录(TTL决定缓存有效期)

扩展DNS-Prefetch(DNS 预解析)  是一种前端优化技术,用于提前解析网页中可能访问的域名,以减少后续请求的 DNS 查询延迟。

工作原理

  1. 浏览器在解析 HTML 时,发现 <link rel="dns-prefetch" href="//example.com"> 标签
  2. 在后台(不阻塞页面渲染)提前对该域名(如 example.com)进行 DNS 查询
  3. 当用户真正访问该域名的资源(如图片、API 等)时,DNS 已缓存,节省解析时间

2.建立TCP连接

在千辛万苦得到目标服务器的真实IP地址后,接着就是建立TCP连接了

具体建立连接的方式为:

  1. 三次握手:通过三次握手确保服务器和客户端能够正常建立连接
  2. 传输数据:客户端和服务器可以进行传输数据
  3. 四次挥手:在连接断开的阶段,会使用四次挥手的方法确保连接能够正常断开

当然如果是HTTPS,还需进行TLS握手协商加密算法和交换密钥。

3. 发送HTTP请求

建立了客户端和服务器的TCP连接后,应用层的HTTP可以基于传输层的TCP发送请求

发送请求需要携带三样东西:请求行、请求头、请求体(仅部分请求方法需要)

4.网络响应

在服务器接收到客户端发送的请求后,会把需要的HTML、JS、CSS、图片等数据返回给客户端

响应时同样需要携带:响应行、响应头、响应体

此时观察请求头中的Conntection是否为Keepalive,如果为keepalive的话,此时不会立即四次挥手断开连接,如果不为keepalive的话,此时会断开连接

至此,网络阶段就描述完了,接下来讲讲渲染阶段

渲染阶段

渲染阶段就是将上述网络阶段收到的HTML CSS JS等数据,通过浏览器引擎、JS引擎、GUI渲染引擎的协作,最终将页面展示给用户的流程:

首先,GUI引擎需要将返回的HTML文件进行转换成字符,token化、转节点的一系列操作变成DOM树,在这个过程中,也会同步建立CSSOM树,当然也可能会遇到JS线程的阻塞,

具体来说,当在解析构建DOM树时,如果遇到了link=".css"的标签,会触发CSS的下载,此时会进行CSSOM树的构建,具体来说,CSSOM树的构建也会进行token化、构建节点等一系列操作,它是和DOM树的构建同步进行的,当解析构建DOM树时,遇到了script相关的标签,会将控制权由gui线程转交给JS线程,由于它们的互斥的,此时GUI线程会挂起,JS线程会执行JS代码,阻塞渲染,意味着会阻塞CSSOM树和DOM树的构建。

如果在不考虑遇到JS线程的阻塞,渲染线程正常的情况下,待CSSOM树和DOM树都构建完成后,会合并两棵树,得到render树,render树此时树上的节点会由DOM树的节点和CSSOM树的节点的合并,但是当前还不能确定每个元素节点在页面上的具体位置,所以就需要根据计算布局,将render树转变成Layout树,旨在计算每个元素具体在页面上的布局位置,待布局转变完毕之后,会进行绘制过程,我们也称为栅格化,目的是将render树转换为到页面上像素,

然后进入到合成阶段,合成阶段会使用合成器根据z-index,分层的位置、透明度等属性,将多层图层进行一个合并的操作,每个合成层都是经过绘制过后的图层,最终输出合成后的页面,通过上述的过程后,至此我们能够在页面上看到一个最终的画面。

重绘和回流

在渲染阶段完成后,我们更改一些CSS属性或者页面结构等操作,可能会涉及重绘和回流

首先讲讲重绘,重绘是指当css的某些样式发生改变使得可变性发生改变,例如更改文字颜色,背景透明度等不影响布局时,会使得浏览器重新绘制当前已改变样式的部分,具体来说会在render树更改需要重绘的部分,然后进行一次重新绘制

然后讲讲回流,回流也叫重排,是指css的某些样式发生改变或者页面的结构发生改变时,导致当前页面布局发生改变或者DOM结构发生改变,此时会触发重排操作,具体来说在更改render树,并且会重新计算并更新layout树,再根据计算更新后的layout树和更改后的render树进行一次重新绘制

重绘不一定会重排,重排一定会重绘!所以显而易见,重排的性能消耗相对较大,我们在实际开发中需要避免重排,常常有以下几种方式可以帮助减少或避免重排

  1. 同一更改css样式,将多次css样式的修改集中为单次
  2. 使用合成层的GPU独立渲染机制:在某些情况下,可以设置元素的transform、opcaity等属性,生成一个新的图层
  3. react的框架使用了diff算法和虚拟DOM来减少真实DOM的操作,间接避免重排

总结

上述就是我关于在输入url后,浏览器做了什么的回答,主要是通过自己捋一遍,自己独立表达一遍的过程巩固温习这个面试中的常考问题,有很多不严谨的地方,希望各位大佬海纳!