从url输入到页面渲染:深挖浏览器渲染的完整过程

180 阅读9分钟

每次你打开一个网站,你已经对上面的出现的内容习以为常,然而,在某一瞬间,你又突然对它感到好奇。

它上面的内容是如何显示出来的?

从你在地址栏输入一个 URL,到屏幕上呈现出完整的网页,这一过程看似瞬间完成,然而,背后却隐藏着浏览器与服务器之间精密协作的复杂机制。

先说结论,从url输入到页面渲染过程分为以下步骤:

  • DNS 解析 :将域名(如 juejin.com)转换为对应的 IP 地址
  • 建立 TCP 连接 :通过 三次握手 ,确保浏览器与服务器之间的通信可靠性。
  • 发送 HTTP 请求 :浏览器通过 TCP 连接,向服务器请求资源(如 HTML、CSS、JS)的过程。
  • 服务器处理并返回响应 :服务器处理请求,返回包含资源内容的 HTTP 响应
  • 浏览器解析与渲染页面 :浏览器解析 HTML和 CSS,生成渲染树,并通过一系列操作将代码转化为网页。
  • 断开连接 :TCP通过 四次挥手 终止 TCP 连接

一、DNS 解析

当用户在地址栏输入 URL(如 https://juejin.cn/)后,浏览器会通过 DNS 解析 将域名转换为对应的 IP 地址。

名词解释

URL: 一个用于标识互联网上资源位置的地址。

IP地址 :用于标识网络中每个设备的唯一数字标签,它能够使设备相互定位和通信。

流程分析

  • 浏览器先检查本地 DNS 缓存(操作系统或浏览器缓存)。

  • 若无缓存,向递归 DNS 服务器发起查询,最终通过权威 DNS 服务器获取 IP 地址。

    就像是你去朋友家玩,但不知道他家的地址,你先翻看自己的通讯录(本地缓存)看看是否有记录, 如果没有,就打电话问朋友(递归 DNS 服务器),朋友再查他的家庭地址(权威 DNS 服务器)告诉你。

二、建立 TCP 连接

通过 IP 地址,浏览器与服务器建立 TCP 连接,通过 三次握手 确保通信的可靠性。

名词解释

三次握手

  • 客户端向服务器发送一个 SYN(同步)消息,表示请求建立连接,并进入SYN\_SENT状态。
  • 服务器接收到 SYN 请求后,会回复一个 SYN-ACK 消息给客户端,表示同意建立连接。
  • 客户端收到服务器的 SYN-ACK 后,发送一个 ACK(确认)消息作为回应,确认收到了服务器的 SYN 并完成连接的最后一步。

image.png

SYN:全称Synchronize Sequence Numbers,意味着客户端请求与服务器同步序列号,以准备建立一个连接,这是一个开始对话的信号。

SYN_SENT:表示客户端已经发出了同步请求,正在等待服务器的响应。在这个状态下,客户端期待从服务器接收到一个 SYN-ACK 作为回应。

SYN-ACK:服务器在接收到客户端的 SYN 后,会发送一个 SYN-ACK 作为响应,SYN 部分表示服务器同意同步序列号,而 ACK 部分则是对客户端 SYN 的确认。

ACK:表示客户端收到了服务器的 SYN-ACK 响应,并且双方现在都已经准备好进行数据传输。完成这一步骤后,连接建立,可正常数据通信。

举个例子

就像是你和朋友约好见面,需要确认双方都准备好了。

你发短信:“明天下午三点在咖啡馆见,你来吗?”(SYN 请求)。

朋友回复:“我到时间一定到,你也来吧!”(SYN-ACK 响应)。

你回复:“收到,明天见!”(ACK 确认)。

三、发送 HTTP 请求

浏览器通过 TCP 连接向服务器发送 HTTP 请求报文,请求 HTML 文件及关联资源(如CSS、JS 等)。

名词解释

HTTP 请求报文:客户端(如浏览器)向服务器发送的一种数据格式,用于请求资源或执行操作,它主要由以下几个部分组成:

  • 请求行 :包含请求方法(如 GETPOST)、请求的资源路径(如 /index.html)、以及使用的HTTP版本(如 HTTP/1.1)。

  • 请求头 :提供关于请求的附加信息,如客户端类型(User-Agent)、接受的内容类型(Accept)、主机名(Host)等。

  • 请求体 :对于某些请求方法(如 POSTPUT),可能包含要发送给服务器的数据,比如表单数据或文件内容。

四、服务器处理并返回响应

服务器接收请求后,处理逻辑并返回HTTP响应报文,其中包含 HTML 内容及状态码

名词解释

状态码:服务器通过HTTP响应报文返回给客户端的一个三位数字代码,用于表示请求的处理结果,它可以让客户端快速了解操作是否成功、需要采取什么进一步行动或是否有错误发生。

常见的状态码分类如下:

  • 2xx(成功) :如 200 OK,表示请求已成功处理。
  • 3xx(重定向) :如 301 Moved Permanently,表示资源已永久移动到新位置,需客户端进行额外操作以完成请求。
  • 4xx(客户端错误) :如 404 Not Found,表示客户端发出的请求有误,服务器无法找到请求的资源。
  • 5xx(服务器错误) :如 500 Internal Server Error,表示服务器在处理请求时发生了错误。

五、浏览器解析与页面渲染

该过程核心步骤如下图所示

ae7aa55c42430c2139c5db346e112a57.png

1. 解析 HTML(HTML Parser):构建 DOM 树

过程

  • 字节流解析:浏览器通过网络请求获取HTML文件的字节流(如HTTP响应),根据文件的编码(如UTF-8)将其转换为字符流。

  • 令牌化(Tokenization) :HTML解析器通过状态机逐字符解析字符流,识别标签名(如<div>)、属性(如id="box")等,并生成标记(Token)。

  • DOM节点生成:每个标记会被转换为对应的DOM节点对象。

举个例子:

<div id="box"></div>

其在内存中存储格式简单描述(真实的 DOM 节点在浏览器中是一个更复杂的对象,下面只是简略版,但核心逻辑相同)为:

{
 type: 'div',
 attrs: { 
         id: 'box'
        },
 children: [...] 
 }

最终,一步步递归后,构建成一棵完整的DOM树。

关键

  • 阻塞行为:遇到<script>标签时,解析会暂停,优先执行脚本(除非使用asyncdefer属性)。
  • 动态更新:通过JavaScript修改DOM时,会触发DOM树的重新构建(重排)。

2. 解析 CSS(CSS Parser):构建 CSSOM 树

过程

  • 样式表解析:浏览器解析<style>标签、<link>引入的CSS文件,以及内联样式。

  • CSSOM树生成:将CSS规则转换为CSSOM树,以下列代码为例:

 div#box {
      color: red;
 }
 p {
      margin: 0;
 }

 <div id="box">
    <p></p>

其在内存中存储格式的简单描述为:

    {
      selectors: ["div#box", "p"],
      styles: {
        "div#box": { 
        color: "red"
        },
        "p": {
        margin: "0" 
        }
      }
    }

关键

  • 层叠规则:通过选择器优先级(如!important、ID选择器、类选择器)确定最终样式。
  • 阻塞渲染:CSSOM的构建会阻塞渲染树的生成,直到所有样式表加载完成(除非使用@import或异步加载)。

3. 生成渲染树(Render Tree)

过程

  • 合并DOM和CSSOM:浏览器将DOM树和CSSOM树合并,生成渲染树(Render Tree)。

  • 过滤不可见元素

    • 排除display: none的元素。
    • 排除不在当前视口内的元素(如懒加载图片)。

关键

  • 渲染树的结构:仅包含可见元素及其样式信息。
  • 动态更新:当DOM或CSSOM变化时,渲染树会重新生成。

4. 布局(Layout):计算几何位置

过程

  • BFC与IFC

    • BFC(块级格式化上下文) :由overflow: hiddenfloat等属性触发,独立于父容器的布局。
    • IFC(行内格式化上下文) :处理文本和行内元素的布局。
  • 盒子模型计算

    • 计算每个元素的widthheightmarginpaddingborder等属性。
    • 根据文档流(Normal Flow)确定元素的位置(如块级元素从上到下排列,行内元素从左到右排列)。

关键

*   **重排(Reflow)** :布局计算称为重排,是性能开销最大的阶段之一。
*   **触发重排**:修改元素的几何属性(如`width``height`)会触发重排。

5. 分层(Layering):图层划分

过程

  • 图层触发条件

    • 使用transformopacityfilter等属性。
    • 元素设置position: fixedz-index
    • 视频、Canvas等特殊元素。
  • 图层管理

    • 每个图层独立绘制,修改图层内容时仅需重新绘制该图层(而非整个页面)。
    • GPU加速:图层绘制由GPU处理,提升性能。

关键

  • 过度分层:过多图层会增加内存占用和合成成本,需合理使用。

6. 绘制(Paint):像素化渲染

过程

  • 像素生成

    • 将图层分解为像素信息(如颜色、形状、文本),生成位图。
    • 处理复杂效果(如阴影、渐变、抗锯齿)。

关键

  • 重绘(Repaint) :当元素样式变化但不影响布局时(如colorbackground),触发重绘。
  • 绘制开销:重绘成本较高,需避免频繁操作(如闪烁动画)。

7. 合成(Composite):最终画面输出

过程

  • 图层合成

    • 浏览器将所有图层按z-index顺序提交给GPU。
    • GPU将图层合成为最终画面,并输出到屏幕。

关键

  • 硬件加速:通过GPU合成提升性能,尤其适合动画和复杂页面。
  • 优化策略:减少图层数量、避免过度合成(如不必要的透明度或阴影)。

由于篇幅太长,对于该模块内容,如果想要进行更深入的了解,欢迎阅读《# 从url输入到页面渲染(二):解析和渲染过程详解》


六、断开连接

当页面显示出内容后,TCP 通过四次挥手,终止 TCP 连接,确保双方都能安全、有序地关闭连接。

名词解释

四次挥手

  • 客户端发送 FIN:客户端(浏览器)告知服务器:“我已无数据发送,请求关闭连接。”

  • 服务器回应 ACK:服务器确认收到 FIN,并发送 ACK 表示同意关闭。

  • 服务器发送 FIN:服务器主动发送 FIN,表示自己也无数据发送。

  • 客户端回应 ACK:客户端确认收到 FIN,连接彻底关闭。

FIN: TCP 协议中用于关闭连接的控制标志位(Finish),它的作用是告诉对方:“我已经完成数据发送,请求关闭连接”。


本文为作者的理解,如果内容有误,欢迎各位读者在评论区指正。

最后,都看到这了,如果觉得这篇文章对你有所帮助,不妨动动小手,点赞 + 收藏 !🌟

99db98bccf5c6a316b4efb1f323da9a0.gif