地址栏URL回车
- URL 解析
- 查找强缓存
- DNS 查询
- TCP 连接
- HTTP 请求
- 响应请求
- 页面渲染
# URL 解析
# 查找强缓存
先检查强缓存,如果命中直接使用,否则进入下一步
首先通过 Cache-Control 验证强缓存是否可用
如果强缓存可用,直接使用
否则进入协商缓存,即发送 HTTP 请求,服务器通过请求头中的 If-Modified-Since 或者 If-None-Match 这些条件请求字段检查资源是否更新
- 若资源更新,返回资源和 200 状态码
- 否则,返回 304,告诉浏览器直接从缓存获取资源
# DNS 查询
在 TCP 握手之前就已经进行了 DNS 查询,这个查询是操作系统自己做的。当你在浏览器中想访问 www.google.com 时,会进行一下操作:
操作系统会首先在本地缓存中查询 IP
没有的话会去系统配置的 DNS 服务器中查询
如果这时候还没得话,会直接去 DNS 根服务器查询,这一步查询会找出负责 com 这个一级域名的服务器
然后去该服务器查询 google 这个二级域名
接下来三级域名的查询其实是我们配置的,你可以给 www 这个域名配置一个 IP,然后还可以给别的三级域名配置一个 IP
以上介绍的是 DNS 迭代查询,还有种是递归查询,区别就是前者是由客户端去做请求,后者是由系统配置的 DNS 服务器做请求,得到结果后将数据返回给客户端。
最终,获取到了域名对应的目标服务器 IP 地址
# TCP 连接
Chrome 在同一个域名下要求同时最多只能有 6 个 TCP 连接,超过 6 个的话剩下的请求就得等待
在确定目标服务器服务器的 IP 地址后,则经历三次握手建立 TCP 连接
建立 TCP 连接经历了下面三个阶段:
- 通过三次握手(即总共发送 3 个数据包确认已经建立连接)建立客户端和服务器之间的连接。
- 进行数据传输。这里有一个重要的机制,就是接收方接收到数据包后必须要向发送方确认, 如果发送方没有接到这个确认的消息,就判定为数据包丢失,并重新发送该数据包。当然,发送的过程中还有一个优化策略,就是把大的数据包拆成一个个小包,依次传输到接收方,接收方按照这个小包的顺序把它们组装成完整数据包。
- 断开连接的阶段。数据传输完成,现在要断开连接了,通过四次挥手来断开连接。
# HTTP 请求
当建立 tcp 连接之后,就可以在这基础上进行通信,浏览器发送 http 请求到目标服务器
请求的内容包括:
- 请求行
- 请求头
- 请求主体
# 响应请求
当服务器接收到浏览器的请求之后,就会进行逻辑操作,处理完成之后返回一个 HTTP 响应消息,包括:
- 状态行
- 响应头
- 响应正文
在服务器响应之后,由于现在 http 默认开始长连接 keep-alive,当页面关闭之后,tcp 链接则会经过四次挥手完成断开
# 页面渲染
当浏览器接收到服务器响应的资源后,首先会对资源进行解析:
查看响应头的信息,根据不同的指示做对应处理,比如重定向,存储 cookie,解压 gzip,缓存资源等等
查看响应头的 Content-Type 的值,根据不同的资源类型采用不同的解析方式 关于页面的渲染过程如下:
解析 HTML,构建 DOM 树
解析 CSS ,生成 CSS 规则树
合并 DOM 树和 CSS 规则,生成 render 树
布局 render 树( Layout / reflow ),负责各元素尺寸、位置的计算
绘制 render 树( paint ),绘制页面像素信息
浏览器会将各层的信息发送给 GPU,GPU 会将各层合成( composite ),显示在屏幕上
# 参考文献
- https://github.com/skyline75489/what-happens-when-zh_CN (opens new window)
- https://github.com/febobo/web-interview/edit/master/docs/http/after_url.md (opens new window)
- https://sanyuan0704.top/my_blog/blogs/browser/browser-render/001.html (opens new window)
- https://sanyuan0704.top/my_blog/blogs/perform/001.html (opens new window)