【浏览器】浏览器访问URL全过程

浏览器访问URL全过程

相关文章

浏览器访问URL全过程


一、输入URL

用户在浏览器地址栏中输入URL,或者点击页面上的链接。

二、浏览器查找域名的 IP 地址

  • 解析本地 hosts:浏览器首先查找本地 hosts 文件,找到对应的 IP 地址。如果没有,就向本地 DNS 服务器发送 DNS 请求。
  • 本地 DNS 服务器:本地 DNS 服务器收到请求后,会先查看缓存中是否有对应记录,如果没有则向根 DNS 服务器发送请求。
  • 根 DNS 服务器:根 DNS 服务器告诉本地 DNS 服务器应该去查询哪个顶级域名服务器。
  • 域名服务器:域名服务器返回域名和 IP 地址对应关系。
  • 返回结果并缓存:本地 DNS 服务器将 IP 地址返回给浏览器,并缓存该对应关系以便下次查询加快速度。

三、建立TCP连接

三次握手

  • 客户端向服务器发送 SYN 包(SYN=1,ACK=0),表示请求建立连接。
  • 服务器收到 SYN 包后,如果同意建立连接,则发送 SYN+ACK 包(SYN=1,ACK=1),表示连接已被正确建立。
  • 客户端收到 SYN+ACK 包后,发送 ACK 包(ACK=1),表示确认收到服务器的确认,连接建立完成。

四、浏览器发起HTTP请求

一旦TCP连接建立,浏览器将发送HTTP请求到目标服务器。这个请求包含了请求方法(例如GET、POST)、URL、请求头等信息。

五、TCP传输报文

位于传输层的TCP协议为传输报文提供可靠的字节流服务。 它为了方便传输,将大块的数据分割成以报文段为单位的数据包进行管理,并为它们编号,方便服务器接收时能准确地还原报文信息(MTU)。

六、服务器返回响应

浏览器接收到服务器发送的HTTP响应后,会对其进行解析,并根据响应头中的信息决定如何处理响应内容。

七、页面渲染

当浏览器的网络线程收到 HTML 文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。

在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。

1、HTML 解析 - ParseHTML (渲染线程)

构建DOM树

渲染主线程会根据HTML标记构建DOM(文档对象模型)树。

构建CSSOM树

同时,渲染主线程也会根据页面中的CSS样式信息构建CSSOM(CSS对象模型)树。

2、生成render树 (渲染线程)

渲染主线程根据 DOM 树,依次为树中的每个节点计算出它最终的样式,称之为 Computed Style。

在这一过程中,很多预设值会变成绝对值,比如red会变成rgb(255,0,0);相对单位会变成绝对单位,比如em会变成px。

3、计算布局 (渲染线程)

渲染主线程根据渲染树的结构和样式信息,计算每个元素在页面上的位置和大小,称为布局或回流。

  • 计算盒模型尺寸:元素的内容、内边距、边框和外边距尺寸由 CSS 样式和内容决定。

  • 计算文档流:根据 CSS 规则和文档流顺序确定元素位置,包括块级元素和行内元素。

  • 计算相对定位和浮动元素:调整相对定位元素位置和浮动元素排列。

  • 计算大小和位置:考虑元素的各项属性,如宽度、高度、边距、内边距等。

  • 确定堆叠顺序:根据 z-index 属性确定重叠元素显示顺序。

布局完成后会得到布局树。

4、分层 (渲染线程)

渲染主线程根据一定的规则将页面内容划分为多个图层,通常是以一些特定的HTML元素或CSS属性为标志。

分层的好处在于,将来某一个层改变后,仅会对该层进行后续处理,从而提升效率。

图层的创建条件:

  • 3D 变换:具有 3D 变换属性(如 transform: translate3d()、transform: scale3d()、transform: rotate3d() 等)的元素通常会被单独分配到一个图层。
  • will-change 属性:使用 will-change 属性明确告知浏览器元素将要发生什么变化,以便浏览器提前为该元素创建图层。
  • 视频、canvas、iframe 元素等具有特殊绘制属性的元素也可能会被分配到单独的图层。

5、绘制 (渲染线程)

渲染主线程为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。

这一步结束后,渲染主线程的工作到此为止,剩余步骤交给其他线程完成。

6、分块 (合成线程)

完成绘制后,主线程将每个图层的绘制信息提交给合成线程,剩余工作将由合成线程完成。

合成线程首先对每个图层进行分块,将其划分为更多的小区域。以便后续操作优先处理靠近视口的块。

它会从线程池中拿取多个线程来完成分块工作。

7、光栅化 (GPU 进程)

分块结束后,合成线程会将块信息交给 GPU 进程,以极高的速度完成光栅化。

光栅化就是将每个块变成位图,此过程会用到 GPU 加速。

光栅化的结果,就是一块一块的位图。

8、合成和显示(合成线程、浏览器进程)

所有图块都被栅格化,合成线程就会生成一个绘制图块的命令,“DrawQuad”,然后 将该命令提交给浏览器进程。

浏览器进程里面有一个叫viz的组件,用来接收合成线程发过来的DrawQuad命令,然后根据 DrawQuad命令将其页面内容绘制到内存中,最后将内存显示在屏幕上。

八、扩展知识

何时发生回流

  • 页面初始渲染:
    当浏览器首次加载页面时,会进行初始的渲染过程,这个过程中会发生回流。

  • DOM 结构变化:
    当 DOM 结构发生变化时,比如新增、删除、修改元素,或者元素的尺寸、位置发生变化时,可能会触发回流。例如,通过 JavaScript 添加或移除元素、改变元素的样式、尺寸或位置等操作都可能导致回流。

  • 布局属性查询:
    当访问某些与元素布局相关的属性时,比如 offsetWidth、offsetHeight、clientWidth、clientHeight、getComputedStyle 等,浏览器会触发回流。因为这些属性的值是需要重新计算的,所以会引发回流。

  • 窗口尺寸变化:
    当浏览器窗口尺寸发生变化时,页面布局会受到影响,因此可能会触发回流。

  • 字体大小变化:
    如果页面中的文本字体大小发生变化,那么文本所在的容器大小也会受到影响,从而可能导致回流。

何时发成重绘

  • 样式更改:

    当元素的样式属性发生变化时,会触发重绘。这包括修改元素的背景颜色、文字颜色、边框样式、阴影等。

  • 修改元素可见性:

    当通过修改元素的可见性属性(如 visibility 或 opacity)来显示或隐藏元素时,会触发重绘。

  • 触发 CSS 动画:

    使用 CSS 动画(如 transform 和 opacity)进行动画操作时,会触发重绘。

如何避免重绘和回流

  • 使用 CSS3 动画代替 JavaScript 动画:

    CSS3 动画(如 transform 和 opacity)可以利用硬件加速,不会触发回流。相比之下,使用 JavaScript 进行动画操作通常会引发多次回流。

  • 批量修改样式:

    避免通过 JavaScript 一次性修改多个样式属性,而是尽可能地批量修改样式。可以通过将要修改的样式属性放在一个类中,然后一次性添加或移除这个类来实现。

  • 使用 DocumentFragment 进行 DOM 操作:

    在将多个 DOM 元素插入文档中时,可以使用 DocumentFragment 进行操作,以减少回流。DocumentFragment 是一个轻量级的 DOM 节点,可以在其中操作多个子节点,然后一次性将它们插入到文档中。

  • 避免频繁查询布局信息:

    避免在 JavaScript 中频繁查询布局信息(如 offsetWidth、offsetHeight 等),因为这会触发浏览器进行回流。可以通过缓存布局信息或优化代码逻辑来减少对布局信息的查询次数。


喜欢这篇文章?打赏一下支持一下作者吧!
【浏览器】浏览器访问URL全过程
https://www.cccccl.com/20210401/浏览器/浏览器访问URL全过程/
作者
Jeffrey
发布于
2021年4月1日
许可协议