深入探讨浏览器渲染过程

浏览器的渲染过程是多个线程、进程和阶段的复杂编排,它将原始的 HTML、CSS 和 JavaScript 转换为屏幕上的交互像素。虽然讨论浏览器的渲染过程的话题已经并不是什么新鲜事了,而且关于这方面的内容也是足够多了。对我来说,它依然是一个有趣的话题,激励我写出这篇文章。本质上,本文的目标是为了了解在以下两个阶段之间发生的所有事情:

  1. 你在浏览器中输入一个 URL 并按下回车键

  2. 网站在你的屏幕上呈现出来

注意:本文中,我将使用 “客户端(client)”、“浏览器(browser)” 和 “服务器(server)” 这几个术语。在这里,“浏览器” 是一种 “客户端”,在本文的语境中,它们是一个东西,而 “服务器”是指托管网站的网络服务器。

导航与网络

当你在浏览器的地址栏中输入一个 URL 并按下回车键时,渲染过程就开始了。假设我们正在尝试加载 “https://example.com”。浏览器不知道从哪里获取这个网站的内容。这只是一个我们人类能够理解的名称,浏览器理解不了——它需要将这个名称转换为一个 IP 地址——这就是 DNS 查找发挥作用的地方了。

提示:DNS 代表域名系统(Domain Name System)。这个系统使用指定的权威域名服务器将域名映射到数字 IP 地址。

DNS 查询步骤 Demo 演示:

上图展示了 DNS 的查找过程,也称为查询之旅(query journey)。查询之旅涉及将你输入的域名转换为 IP 地址所需的每一个步骤。查询的第一站是递归服务器(recursive server),然后它会联系一系列权威域名服务器将域名转换为 IP 地址。最终,返回请求域名所对应的 IP 地址。

提示:域名服务器是用于查找 IP 地址所关联域名的专用服务器。你可以在域名的 DNS 记录(domain’s DNS records)中找到这些域名服务器。

现在我们有了 IP 地址,浏览器就可以与托管网站的服务器建立连接了。建立连接是通过 TCP 握手过程完成的。

TCP/TLS 握手

TCP(传输控制协议)握手是一个包含三个步骤的过程,用于在客户端和服务器之间建立连接。它由客户端和服务器之间交换的一组数据包组成,以确保连接可靠。这三个步骤分别是:

  1. SYN:客户端向服务器发送一个同步数据包(SYN)来发起连接

  2. SYN-ACK:服务器用一个确认数据包(SYN-ACK)响应客户端

  3. ACK:客户端向服务器发送一个确认(ACK)来完成握手

到这一步,我们只是与服务器建立了连接。下一步是确保这个连接的安全性。还记得 URL 旁边的 “https” 锁图标吗?这定义了一个安全连接,是通过另一个称为 TLS 握手的握手过程完成的,它涉及几个步骤。但在我们深入探讨之前,如果你能理解一些与 TLS 握手相关的术语,会更容易掌握。

  1. 密码(Cipher):一种用于加密和解密数据的算法,用于在互联网上安全地传输数据

  2. 证书(Certificate):一个文件,包含有关网站身份和公钥(public key)的信息,用作数字签名来验证网站的真实性

  3. 证书颁发机构(Certificate Authority,CA):一个受信任的实体,向网站颁发数字证书,由它来验证网站的身份并确保证书的真实性

  4. 公钥(Public Key):用于加密发送至互联网的数据,在服务端与客户端中共享,确保建立安全连接

  5. 私钥(Private Key):用于解密从客户端收到的数据,它是保密的,不对外共享

TLS 握手过程包含多个步骤,我将它主要概括为 4 个类别:

  1. 问候消息(Hello Messages):客户端发送一个 “ClientHello” 消息来发起握手,服务器用一个 “ServerHello” 消息加上数字证书进行响应

  2. 密钥交换(Key Exchange):服务器可发送密钥交换信息,客户端则回应自己的密钥交换信息(如有要求,还可提供证书)

  3. 密码规范(Cipher Spec):客户端发送一个 “CipherSpec” 消息以切换到协商好的加密方式,然后发送一个 “Finished” 消息

  4. 服务器完成(Server Finalization):服务器回复自己的 “CipherSpec” 和 “Finished” 消息,完成握手并建立安全连接

提示:SSL,即安全套接层(Secure Sockets Layer),是最初为 HTTP 开发的安全协议。近来年,SSL 被 TLS(即传输层安全协议)所取代。尽管 “SSL” 这个名称仍然被广泛使用,实际上现在 SSL 握手改成是 TLS 握手才是更符合实际的。

让我们通过下面的演示来看看这个过程:

到这一步,还没有实际的内容或应用程序数据被传输。服务器只是确认了连接并建立了一个安全通道。浏览器(客户端)在幕后处理所有这些协商过程。只有在 TLS 握手完成并且双方都交换了 “Finished” 消息之后,他们才能开始安全地发送和接收加密内容。

HTTP 请求/响应周期

现在浏览器请求网站的内容。服务器处理这个请求并发送回一个响应。这就是 HTTP 请求/响应周期发挥作用的地方。后端开发人员负责处理请求,而前端开发人员更关注这个周期的响应部分

观看下面的演示来可视化这个周期(HTTP 请求流):

我们在上面的演示中看到了一个叫做 “TTFB” 的东西。TTFB 代表首次字节时间(Time To First Byte)。它是客户端请求发送到服务器之后、服务器发送响应返回、直到客户端接收到第一个字节时,这中间所耗费的时间。它是衡量服务器响应时间和网站性能的一个重要指标。较低的 TTFB 表示服务器响应更快。

提示:良好的 TTFB 值应该是 0.8 秒或更少大于 1.8 秒就属于较差的了。介于两者之间的值属于 “需要改进”。

正如你在演示中看到的,在收到第一个字节后,响应继续加载。服务器仍在处理请求并将剩余数据发送回客户端。从这里,浏览器开始介入处理响应。

标记化(Tokenization)

浏览器将开始解析这个 HTML 响应。它读取 HTML 的原始字节,并根据文件指定的编码(如 UTF-8)将它们转换为单个字符。以下是原始字节可能的一个样子:

01001000 01010100 01001101 01001100

提示:每组八个比特代表一个字节,每个字节可以根据编码标准转换为一个字符、符号或指令。例如,在 UTF-8 编码中,字母 A 的二进制序列是 01000001,字母 B 则是 01000010

浏览器将字符串字符转换为不同的标记(tokens)并对它们进行分组,例如,<html><body> 以及尖括号内的其他字符串,每个标记都是一个有意义的单元,代表一个 HTML 组件。

HTML 标记化 Demo:

DOM 树创建

DOM(文档对象模型)树是 HTML 文档结构的层次表示。它将元素表示为节点树,每个节点代表文档中的一个元素、属性或文本内容。:

作为参考,这是我们收到的响应定义成一个简单的 HTML 文档,类似于下面这样:主要有一个 h1 标签、一个  p 标签、一个 a 标签和一点 CSS 样式。

<html lang="en-US">
  <head>
    <style>
      .heading {
        color:#0099ff; 
        font-size: 14px
      }
      p {
        margin: 0.5em 0;
      }
      a {
        color: #0099ff; 
        text-decoration: underline;
      }
    </style>
  </head>
  <body>
    <h1 class="heading">My Page</h1>
    <p>A paragraph with a <a href="https://example.com/about">link</a></p>
  </body>
</html>

DOM 是一个树状结构,所以可以很容易的表示父子关系。

每次浏览器渲染网页时,它都会经历这个多步骤的过程:将 HTML 字节解析为字符,识别标记,将它们转换为节点,最后构建 DOM 树。虽然 DOM 树定义了 HTML 元素的结构和关系,但它并不决定它们的视觉外观。这是由接下来要讲的 CSSOM 决定的。

CSSOM 树创建

CSS 对象模型(CSSOM)是应用于 HTML 文档的 CSS 样式的表示,它类似 DOM 树,但表示的是 CSS 样式而不是 HTML 结构。CSSOM 用于计算文档中每个元素的最终样式。

查看这个演示来了解 CSSOM 树是如何创建的:

浏览器将这些样式解析为一个精简、内存高效且优化的数据结构,旨在有效地组织样式规则,允许根据匹配的选择器快速检索和应用样式。

一旦构建了 DOM 和 CSSOM,浏览器就可以开始创建渲染树了。

渲染树创建

渲染树是 DOM 和 CSSOM 树的组合,它表示页面的视觉结构,包括布局和样式信息。渲染树用于计算布局并在屏幕上绘制元素。

从上面的演示中可以看到,渲染树是 DOM 和 CSSOM 树的组合。它只包含将在屏幕上显示的元素。它为每个元素计算了样式和布局信息,允许浏览器准确地渲染页面。这就把我们带到了渲染过程的最后一个阶段——布局。

布局

你一定使用 CSS 做过定义过不同 “布局“。在浏览器渲染场景, “布局“这个术语,表示计算页面上每个元素的确切位置和大小的过程。

布局过程涉及根据渲染树确定来每个元素的尺寸、边距、填充、边框和定位。你可能见过元素相互重叠,例如模态窗口、下拉菜单等,这就是布局过程发挥作用的地方。

即使 HTML 标记是有序的,由于 CSS 属性会改变布局,元素也不一定按照它们编写的顺序出现。让我们看看这些属性如何影响布局。

写在 HTML 代码里的 DOM 顺序不会改变,但当我们使用 CSS 属性改变布局时,布局过程必须参与处理。当然,其他一些 CSS 属性,诸如 position、display、top、left 和 z - index,同样会影响布局,从而触发布局过程。

从上面的演示中看到的,元素的流受到它们的显示类型(display)的影响:块元素垂直堆叠,而内联元素水平流动;而定位属性如 static, relative, absolute, fixed 和 sticky 则进一步决定了元素如何相互排列——例如,相对定位使元素偏离其正常位置而不影响周围的布局,而绝对定位使元素完全脱离文档流。

经过布局这一步骤,就得到了一个显示每个元素的精确计划。接下来就进入到绘制步骤了,在这个步骤中 HTML 文档最终以视觉形式被渲染到屏幕上。

绘制

在绘制阶段,浏览器将从上一步拿到的结构化布局信息翻译出来,将页面中的每个元素绘制到屏幕上。这个过程设计填充颜色、应用图片、边框、阴影和其他视觉样式,绘制顺序基于堆叠上下文(stacking context),确保元素根据 z-index 和其他属性正确分层。

绘制阶段演示 Demo:

绘制过程也是会优化的,以尽量减少需要重新绘制的像素数量。浏览器使用分层(layering)、合成(compositing)和缓存(caching )等技术来提高页面渲染效率。

拓展内容

JavaScsript 扮演的角色

本文中没有讨论浏览器如何解析和优化  JavaScript,这是一个完全不同的故事。简单说,它会在初始渲染后操作 DOM 和 CSSOM,创建动态和交互式的网页体验。

浏览器渲染引擎

不同的浏览器使用不同的渲染引擎,如 Blink(Chrome)、WebKit(Safari)和 Gecko(Firefox)。这些引擎可能具有不同的性能特征和兼容级别。某些 CSS 功能或 JavaScript 方法可能在一个引擎中支持,但在其他引擎中不支持,或者它们的行为可能不一致。此外,不同的引擎对 HTML 元素所应用的默认样式也可能有所差异。

总结

最后,总结一下浏览器渲染过程的所有步骤:

  1. DNS 查找:当输入 URL 时,浏览器执行 DNS 查找,将域名转换为 IP 地址,以便定位到网站服务器

  2. TCP/TLS 握手:浏览器发起 TCP 握手与服务器建立连接。如果网站是基于 https 的,还会进行 TLS 握手来加密传输的数据

  3. HTTP 请求/响应周期:建立连接后,浏览器发送一个 HTTP 请求获取网站的内容,服务器响应以必要的 HTML、CSS、JavaScript 或其他其他资源

  4. 标记化:浏览器将 HTML 响应的原始数据,将其转换为单个字符,然后转换为标记(如<html><body>

  5. DOM 树创建:浏览器构建 DOM(文档对象模型)树,这是 HTML 文档结构的层次表示,每个节点代表一个元素或文本内容

  6. CSSOM 树创建:浏览器解析 CSS 并创建 CSSOM(CSS 对象模型)树,它表示与 HTML 文档元素相关联的样式

  7. 渲染树创建:DOM 和 CSSOM 树组合形成渲染树,这是页面布局的视觉表示,只包括可见元素及其计算样式

  8. 布局:浏览器根据 CSS 属性(如边距、填充和定位(如 static、absolute))计算屏幕上每个元素的确切大小和位置

  9. 绘制:浏览器基于渲染树将像素绘制到屏幕上,填充颜色、图片、边框和阴影,这些都是由 CSS 定义的

对开发开发人员来说,了解这些底层机制可以帮助你更快、更高效地构建网站。虽然这些步骤之间还涉及其他步骤,但我已尽量涵盖最重要的步骤。

以上这就是本篇文章的全部内容,希望大家喜欢。

原文地址:Exploring the browser rendering process[1],2024.11.03

by Abhishek Saha

参考链接

[1]

Exploring the browser rendering process: https://abhisaha.com/blog/exploring-browser-rendering-process

[2]

Cloudflare DNS Lookup: https://www.cloudflare.com/learning/dns/glossary/dns-lookup/

[3]

Mozilla TCP Handshake: https://developer.mozilla.org/en-US/docs/Glossary/TCP_handshake

[4]

Cloudflare TLS Handshake: https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/

[5]

Mozilla HTTP Request/Response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages

[6]

HTML Spec on Rendering: https://html.spec.whatwg.org/multipage/rendering.html#rendering

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值