输入 URL 到页面渲染的整个流程

一次完整的HTTP事务流程

  1. 域名解析,浏览器根据 DNS 服务器得到域名的 IP 地址
  2. 发起TCP三次握手
  3. 建立TCP连接后向这个 IP 的机器发送 HTTP 请求
  4. 服务器收到、处理并返回 HTTP 请求,浏览器得到HTML代码
  5. 浏览器解析HTML代码,渲染页面

DNS解析域名

DNS 的作用就是通过域名查询到具体的 IP

因为 IP 存在数字和英文的组合(IPv6),很不利于人类记忆,所以就出现了域名。你可以把域名看成是某个 IP 的别名,DNS 就是去查询这个别名的真正名称是什么。

TCP 握手之前就已经进行了 DNS 查询,DNS解析是一个递归查询的过程,具体步骤如下(以www.google.com为例):

  1. 首先在本地域名服务器(最近的一台DNS服务器)中查询IP地址
  2. 如果没有找到,本地域名服务器会向根域名服务器发送一个请求
  3. 如果根域名服务器中也不存在该域名,但判定这个域名属于“com”的一级域,则本地域名服务器会向负责 “com” 这个一级域名的服务器发送一个请求
  4. 如果com一级域名服务器没有找到该域名,但判定这个域名属于“google.com”的二级域,则本地域名服务器会google.com二级域名服务器发送一个请求,以此类推
  5. 直到本地域名服务器得到域名对应的IP地址,并将其缓存到本地,供下次查询使用
  6. 综上,网址的解析过程为.->.com->google.com->www.google.com

DNS 是基于 UDP 做的查询,为什么之前不考虑使用 TCP 去实现?

之前的文章中提到过TCP传输是需要连接的,以及校验数据的准确性,还有三次握手四次挥手,而UDP相对而言无需连接,不会对数据进行处理只是搬用过去,虽然这样不稳定,但确是高效的。

  • TCP - - - DNS域名解析时间 = TCP连接时间 + DNS交易时间
  • UDP - - - DNS域名解析时间 = DNS交易时间

很显然,采用UDP传输,DNS域名解析时间更小。

在很多冷门域名解析的时候,DNS多次迭代查询,如果在此使用的是TCP的话,TCP需要建立多个连接,这多出来的时间不容小觑


TCP三次握手

在之前的文章中已经讲过TCP和UDP的特点和区别了,这里就文章标题而言,简单说下三次握手。

第一次握手
客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。

第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。

第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功


浏览器解析渲染过程

详细过程在之前的文章已经讲过 ,这里简单叙述下过程

  • 根据 HTML 结构生成 DOM
  • 根据 CSS 生成 CSSOM
  • DOMCSSOM 整合形成 RenderTree
  • 根据 RenderTree 开始渲染和展示
  • 遇到<script>时,会执行并阻塞渲染

上文中,浏览器已经拿到了 server 端返回的 HTML 内容,开始解析并渲染。最初拿到的内容就是一堆字符串,必须先结构化成计算机擅长处理的基本数据结构,因此要把 HTML 字符串转化成 DOM 树 —— 树是最基本的数据结构之一。

解析过程中,如果遇到<link href="..."><script src="...">这种外链加载 CSSJS 的标签,浏览器会异步下载,下载过程和上文中下载 HTML 的流程一样。只不过,这里下载下来的字符串是 CSS 或者 JS 格式的。

浏览器将 CSS 生成 CSSOM,再将 DOMCSSOM 整合成 RenderTree ,然后针对 RenderTree 即可进行渲染了。大家可以想一下,有 DOM 结构、有样式,此时就能满足渲染的条件了。另外,这里也可以解释一个问题 —— 为何要将 CSS 放在 HTML 头部?—— 这样会让浏览器尽早拿到 CSS 尽早生成 CSSOM,然后在解析 HTML 之后可一次性生成最终的 RenderTree,渲染一次即可。如果 CSS 放在 HTML 底部,会出现渲染卡顿的情况,影响性能和体验。

最后,渲染过程中,如果遇到<script>就停止渲染,执行 JS 代码。因为浏览器渲染和 JS 执行共用一个线程,而且这里必须是单线程操作,多线程会产生渲染 DOM 冲突。待<script>内容执行完之后,浏览器继续渲染。最后再思考一个问题 —— 为何要将 JS 放在 HTML 底部?—— JS 放在底部可以保证让浏览器优先渲染完现有的 HTML 内容,让用户先看到内容,体验好。另外,JS 执行如果涉及 DOM 操作,得等待 DOM 解析完成才行,JS 放在底部执行时,HTML 肯定都解析成了 DOM 结构。JS 如果放在 HTML 顶部,JS 执行的时候 HTML 还没来得及转换为 DOM 结构,可能会报错。

<script>的标签也不是非要放到底部,因为你可以给 script 标签添加async 或者 defer 属性,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值