关于浏览器:浏览器工作原理

2次阅读

共计 12628 个字符,预计需要花费 32 分钟才能阅读完成。

浏览器(也称为网络浏览器或互联网浏览器)是装置在咱们设施上的软件应用程序,使咱们可能拜访万维网。在浏览这篇文字时,你实际上正在应用一个浏览器。

有许多浏览器正在被应用,截至 2022 年,应用最多的是:谷歌浏览器、苹果的 Safari、微软的 Edge 和火狐。

然而,它们实际上是如何工作的,从咱们在地址栏中键入网络地址开始,到咱们试图拜访的页面显示在屏幕上,会产生什么?

对于这个问题的答案,一个极其简化的版本是:

当咱们从一个特定的网站申请一个网页时,浏览器从网络服务器检索必要的内容,而后在咱们的设施上显示该网页。

很间接,对吗?是的,但在这个看似超级简略的过程中还波及更多的内容。在这个系列中,咱们将探讨 导航 获取数据 解析 渲染 等步骤,并心愿能使你对这些概念更清晰。

1. 导航

导航是加载网页的第一步。它指的是当用户通过 点击一个链接 在浏览器地址栏中写下一个网址 提交一个表格 等形式申请一个网页时产生的过程。

DNS 查问(解决网址问题)

导航到一个网页的第一步是找到该网页的动态资源地位(HTML、CSS、Javascript 和其余类型的文件)。如果咱们导航到 [](https://www.notion.so/842e8b3…)https://example.com,HTML 页面位于 IP 地址为 93.184.216.34 的服务器上(对咱们来说,网站是域名,但对计算机来说,它们是 IP 地址)。如果咱们以前从未拜访过这个网站,就必须进行域名零碎(DNS)查问。

DNS 服务器是蕴含公共 IP 地址及其相干主机名数据库的计算机服务器(这通常被比作电话簿,因为人们的名字与一个特定的电话号码相关联)。在大多数状况下,这些服务器依照要求将这些名字解析或翻译成 IP 地址(当初有 600 多个不同的 DNS 根服务器散布在世界各地)。

因而,当咱们申请进行 DNS 查问时,咱们理论做的是与这些服务器中的一个进行对话,要求找出与 https://example.com 名称绝对应的 IP 地址。如果找到了一个对应的 IP,就会返回。如果产生了一些状况,查找不胜利,咱们会在浏览器中看到一些错误信息。

在这个最后的查问之后,IP 地址可能会被缓存一段时间,所以下次访问同一个网站会更快,因为不须要进行 DNS 查问(记住,DNS 查问只产生在咱们第一次拜访一个网站时)。

TCP (Transmission Control Protocol) 握手

一旦浏览器晓得了网站的 IP 地址,它将尝试通过 TCP 三次握手(也称为 SYN-SYN-ACK,或者更精确的说是 SYN、SYN-ACK、ACK,因为 TCP 有三个音讯传输,用于协商和启动两台计算机之间的 TCP 会话),与持有资源的服务器建设连贯。

TCP 是传输控制协议的缩写,是一种通信规范,使应用程序和计算设施可能在网络上替换信息。它被设计用来在互联网上发送数据包,并确保数据和信息在网络上胜利传递。

TCP 握手是一种机制,旨在让两个想要互相传递信息的实体(在咱们的例子中是浏览器和服务器)在传输数据之前协商好连贯的参数。

因而,如果浏览器和服务器是两个人,他们之间的对话会是这样的:

浏览器向服务器发送一个 SYNC 音讯,要求进行同步(同步意味着连贯)

而后,服务器将回复一个 SYNC-ACK 音讯(SYNChronization 和 ACKnowledgement)

在最初一步,浏览器将回复一个 ACK 信息

当初,TCP 连贯(双向连贯)曾经通过 3 次握手建设,TLS 协商能够开始。

TLS 协商

对于通过 HTTPS 建设的平安连贯,须要进行另一次握手。这种握手(TLS 协商)决定了哪个明码将被用于加密通信,验证服务器,并在开始理论的数据传输之前建设一个平安的连贯。

传输层平安(TLS)是现已废除的安全套接字层(SSL)的继任者,是一种加密协议,旨在通过计算机网络提供通信安全。该协定被宽泛用于电子邮件和即时通讯等利用,但它在确保 HTTPS 平安方面的利用依然是最公开的。因为应用程序能够应用或不应用 TLS(或 SSL)进行通信,因而客户(浏览器)有必要要求服务器建设 TLS 连贯。

在这一步骤中,浏览器和服务器之间还替换了一些信息

  1. 客户端 hello。浏览器向服务器发送一条信息,其中包含它所反对的 TLS 版本和明码套件,以及一串随机字节,称为 客户端随机数
  2. 服务器 hello 和证书 。服务器发回一条信息,其中包含服务器的 SSL 证书、服务器抉择的明码套件和 服务器随机数,这是服务器生成的另一个随机字节串。
  3. 认证。浏览器会向颁发证书的机构核实服务器的 SSL 证书。这样,浏览器就能够确定服务器就是它所说的那个人。
  4. 预主明码 。浏览器会再发送一串随机的字节,称为主密钥,用浏览器从服务器的 SSL 证书 上获取的 公钥 进行加密。主明码只能由服务器用 私钥 解密。
  5. 应用私钥 。服务器解密 预主明码
  6. 创立会话密钥。浏览器和服务器从客户端随机数、服务器随机数和预主明码中生成会话密钥。
  7. 客户端实现。浏览器向服务器发送一个音讯,说它曾经实现。
  8. 服务器实现。服务器向浏览器发送一个音讯,示意它也实现了。
  9. 平安对称加密实现。握手实现,通信能够持续应用会话密钥。

当初能够开始从服务器申请和接收数据了

2. 获取数据

在上一节中,咱们谈到了 导航 ,这是浏览器显示网站的第一步。当初,咱们将进入下一个步骤,看看如何 获取资源

HTTP 申请

在咱们与服务器建设平安连贯后,浏览器将发送一个初始的 HTTP GET 申请。首先,浏览器将申请页面的 HTML 文件。它将应用 HTTP 协定来做这件事。

HTTP(超文本传输协定)是一个获取资源的协定,如 HTML 文件。它是网络上任何数据交换的根底,它是一个客户 - 服务器协定,这意味着申请是由接收者发动的,通常是网络浏览器。

申请办法 – POST, GET, PUT, PATCH, DELETE 等

URI – 是对立资源辨认符的缩写。URIs 用于辨认互联网上的形象或物理资源,如网站或电子邮件地址等资源。一个 URI 最多能够有 5 个局部

scheme:用于阐明应用的是什么协定

authority:用于辨认域名

path:用于显示资源的确切门路

query:用于示意一个申请动作

fragment:用来指代资源的一部分

// URI parts
scheme :// authority path ? query # fragment

//URI example
<https://example.com/users/user?name=Alice#address>

https: // scheme name
example.com // authority
users/user // path
name=Alice // query
address // fragment

HTTP 头字段 – 是浏览器和服务器在每个 HTTP 申请和响应中发送和接管的字符串列表(它们通常对终端用户是不可见的)。在申请的状况下,它们蕴含对于要获取的资源或申请资源的浏览器的更多信息。

如果你想看看这些申请头字段是什么样子的,请进入 Chrome 浏览器并关上开发者工具(F12)。进入 Network 标签,抉择 FETCH/XHR。在上面的屏幕截图中,我刚刚在搜索引擎上搜寻了Palm Springs,这就是申请头的样子。

HTTP 响应

一旦服务器收到申请,它将对其进行解决并回复一个 HTTP 响应。在响应的注释中,咱们能够找到所有相干的响应头和咱们申请的 HTML 文档的内容

状态代码 – 例如:200、400、401、504 网关超时等(咱们的指标是 200 状态代码,因为它通知咱们一切正常,申请是胜利的)响应头字段 – 保留对于响应的额定信息,如它的地位或提供它的服务器。

一个 HTML 文档的例子能够是这样的

<!doctype HTML>
<html>
 <head>
  <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> 我的页面 </title>
  <link rel="stylesheet" src="styles.css"/>
  <script src="mainScripts.js"></script>
</head>
<body>
  <h1 class="heading"> 这个是我的页面 </h1>
  <p> 一个段落和一个 <a href="<https://example.com/about>"> 链接 </a></p>
  <div>
    <img src="myImage.jpg" alt="image description"/>
  </div>
  <script src="sideEffectsScripts.js"></script>
</body>
</html>

对于我后面提到的同一个搜寻,响应头是这样的

如果咱们看一下 HTML 文档,咱们会发现它援用了不同的 CSS 和 Javascript 文件。这些文件不会被申请。在这个时候,只有 HTML 被申请并从服务器接管。

这个初始申请的响应蕴含收到的第一个字节的数据。第一个字节的工夫(TTFB)是指从用户提出申请(在地址栏中输出网站名称)到收到第一个 HTML 数据包(通常为 14kb)的工夫。

TCP 慢启动和拥塞算法

TCP 慢启动 是一种均衡网络连接速度的算法。第一个数据包将是 14kb(或更小),其工作形式是逐步减少传输的数据量,直到达到预约的阈值。从服务器接管到每个数据包后,客户端以 ACK 音讯 响应。因为连贯容量无限,如果服务器发送太多数据包太快,它们将被抛弃。客户端不会发送任何 ACK 音讯,因而服务器会将此解释为拥塞。这就是 拥塞算法 发挥作用的中央。他们监控发送的数据包和 ACK 音讯的流,以确定流量的最佳速率并创立稳固的流量流。

HTML 解析

到目前为止,咱们探讨了导航和数据获取。明天咱们将探讨解析,特地是 HTML 解析

咱们看到在向服务器收回初始申请后,浏览器如何收到蕴含咱们尝试拜访的网页的 HTML 资源(第一块数据)的响应。当初浏览器的工作就是开始解析数据。

解析是指将程序剖析并转换为运行时环境理论能够运行的外部格局

换句话说,解析意味着将咱们编写的代码作为文本(HTML、CSS)并将其转换为浏览器能够应用的内容。解析将由浏览器引擎实现(不要与浏览器的 Javascript 引擎混同)。

浏览器引擎是每个次要浏览器的外围组件,它的次要作用是联合构造 (HTML) 和款式 (CSS),以便它能够在咱们的屏幕上绘制网页。它还负责找出哪些代码片段是交互式的。咱们不应将其视为一个独自的软件,而应将其视为更大软件(在咱们的例子中为浏览器)的一部分。

有许多浏览器引擎,但大多数浏览器应用这三个沉闷且残缺引擎之一:

Gecko 它是由 Mozilla 为 Firefox 开发的。过来,它曾为其余几种浏览器提供反对,但目前,除了 Firefox,Tor 和 Waterfox 是惟一仍在应用 Gecko 的浏览器。它是用 C++ 和 JavaScript 编写的,自 2016 年起,还用 Rust 编写。

WebKit 它次要由 Apple 为 Safari 开发。它还为 GNOME Web (Epiphany) 和 Otter 提供反对。(令人诧异的是,在 iOS 上,包含 Firefox 和 Chrome 在内的所有浏览器也由 WebKit 提供反对)。它是用 C++ 编写的。

Blink,Chromium 的一部分 它最后是 WebKit 的一个分支,次要由 Google 为 Chrome 开发。它还为 Edge、Brave、Silk、Vivaldi、Opera 和大多数其余浏览器我的项目(一些通过 QtWebEngine)提供反对。它是用 C++ 编写的。

当初咱们理解了谁将进行解析,让咱们看看在从服务器接管到第一个 HTML 文档后到底产生了什么。让咱们假如文档如下所示:

<!doctype HTML>
<html>
 <head>
  <title>This is my page</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <h1>This is my page</h1>
  <h3>This is a H3 header.</h3>
  <p>This is a paragraph.</p>
  <p>This is another paragraph,</p>
</body>
</html>

即便申请页面的 HTML 大于初始的 14KB 数据包,浏览器也会开始解析并尝试依据其领有的数据出现体验。HTML 解析波及两个步骤:词法剖析 树结构(构建称为 DOM 树的货色)。

词法剖析

它将一些输出转换为标签(源代码的根本组件)。设想一下,咱们将一段英文文本分解成单词,其中单词就是标签。

词法剖析过程完结时的后果是一系列 0 个或多个以下标签:DOCTYPE、开始标签 (<tag>)、完结标签(</tag>)、自闭合标签 (<tag/>)、属性名称、值、正文、字符、文件结尾或元素中的纯文本内容。

构建 DOM

创立第一个 token 后,树构建 开始。这本质上是基于先前解析的标签创立 树状构造(称为文档对象模型)。

DOM 树形容了 HTML 文档的内容。<html> 元素是文档树的第一个标签和根节点。树反映了不同标签之间的关系和层次结构。咱们有 父节点 ,嵌套在其余标签中的标签是 子节点。节点数越多,构建 DOM 树所需的工夫就越长。上面是咱们从服务器取得的 HTML 文档示例的 DOM 树:

实际上,DOM 比咱们在该模式中看到的更简单,但我放弃简略以便更好地了解(另外,咱们将在当前的文章中更具体地探讨 DOM 及其重要性)。

此构建阶段是 可重入的,这意味着在解决一个 token 时,分词器可能会复原,导致在第一个 token 解决实现之前触发并解决更多 token。从字节到创立 DOM,整个过程如下所示:

解析器从上到下逐行工作。当解析器遇到非阻塞资源(例如图像)时,浏览器会向服务器申请这些图像并持续解析。另一方面,如果它遇到阻塞资源(CSS 样式表、在 HTML 的 <head> 局部增加的 Javascrpt 文件或从 CDN 增加的字体),解析器将进行执行,直到所有这些阻塞资源都被下载。这就是为什么,如果你正在应用 Javascript,倡议在 HTML 文件的开端增加 <script> 标签,或者如果你想将它们保留在 <head> 标签中,你应该向它们增加 defer 或 async 属性(async 容许在下载脚本后立刻执行异步操作,而 defer 只容许在整个文档被解析后执行。)。

预加载器 & 使页面更快

Internet Explorer、WebKit 和 Mozilla 都在 2008 年实现了预加载器,作为解决阻塞资源的一种形式,尤其是脚本(咱们之前说过,当遇到脚本标签时,HTML 解析将进行,直到脚本被下载并执行)。

应用预加载器,当浏览器卡在脚本上时,第二个较轻的解析器会扫描 HTML 以查找须要检索的资源(样式表、脚本等)。而后预加载器开始在后盾检索这些资源,目标是在主 HTML 解析器达到它们时它们可能曾经被下载(如果这些资源曾经被缓存,则跳过此步骤)。

4. 解析 CSS

解析完 HTML 之后,就该解析 CSS(在内部 CSS 文件和款式元素中找到)并构建 CSSOM 树(CSS 对象模型)。

当浏览器遇到 CSS 样式表时,无论是内部样式表还是嵌入式样式表,它都须要将文本解析为可用于设置布局款式的内容。浏览器将 CSS 变成的数据结构称为 CSSOM。DOM 和 CSSOM 遵循类似的概念,因为它们都是树,但它们是 不同的数据结构。就像从咱们的 HTML 构建 DOM 一样,从 CSS 构建 CSSOM 被认为是一个「渲染阻塞」过程。

词法剖析和构建 CSSOM

与 HTML 解析相似,CSS 解析从词法剖析开始。CSS 解析器获取字节并将它们转换为字符,而后是标签,而后是节点,最初它们被链接到 CSSOM 中。浏览器会执行一些称为 选择器匹配 的操作,这意味着每组款式都将与页面上的所有节点(元素)匹配。

浏览器从实用于节点的最通用规定开始(例如:如果节点是 body 元素的子节点,则所有 body 款式都由该节点继承),而后通过利用更具体的规定递归地优化计算出的款式。这就是为什么咱们说款式规定是级联的。

假如咱们有上面的 HTML 和 CSS:

body {
  font-size: 16px;
  color: white;
} 

h1 {font-size: 32px;}

section {color: tomato;}

section .mainTitle {margin-left: 5px}

div {font-size: 20px;}

div p {
  font-size:  8px;
  color: yellow;
}

这段代码的 CSSOM 看起来像这样:

请留神,在下面的模式中,嵌套元素既有 继承的款式(来自父级 – 例如:h1 从 body 继承其色彩,section 从 body 继承其字体大小)和它们本人的款式(能够笼罩继承的规定 是否来自父节点 – 例如:p 笼罩了从 div 继承的色彩和字体大小,而 mainTitle 没有从父节点取得其右边距)。

因为咱们的 CSS 能够有多个起源,并且它们能够蕴含实用于同一节点的规定,因而浏览器必须决定最终利用哪个规定。这就是 优先级 发挥作用的时候,如果您想理解更多相干信息,能够拜访此页面。

设想一下,您在机场寻找您的敌人 John。如果你想通过喊他的名字找到他,你能够喊“John”。可能不止一个 John 会同时呈现在机场,所以他们可能都会做出回应。更好的办法是用他的全名打电话给你的敌人,这样当你喊“John Doe”时,你就有更好的机会找到他,因为“John Doe”比“John”更具体。

同样,假如咱们有这个元素:

<p>
  <a href="<https://dev.to/>">This is just a link!</a>
</p>

以及这些 CSS 款式:

a {color: red;}

p  a {color: blue;}

您认为浏览器会利用哪条规定?答案是第二条规定,因为 p 标签中的所有 a 标签选择器比所有 a 标签选择器都具备更高的优先级。如果你想玩玩优先级,你能够应用这个 优先级计算器。

重点

CSS 规定是从右到左浏览的,这意味着如果咱们有这样的代码:section p {color: blue;}, 浏览器将首先查找页面上的所有 p 标签,而后它会查看这些 p 标签中是否有一个 section 标签作为父标签。如果查找可能命中,它将利用这个 CSS 规定

5. 执行 Javascript

在解析 CSS 并创立 CSSOM 的同时,还会下载其余资产,包含 JavaScript 文件。这要归功于咱们在之前文章中提到的预加载器。

预加载器就像一个解析器,它在主解析器解决 HTML 代码时扫描 HTML 文件。它的作用是查找样式表、脚本或图片(也须要从服务器检索)等资源并申请它们。心愿在解析 HTML 时,这些资源曾经下载并筹备好进行解决。

所以,当咱们从服务器获取 Javascript 文件后,代码被解释、编译、解析和执行。计算机无法了解 Javascript 代码,只有浏览器能够。JS 代码须要被翻译成计算机能够应用的货色,这是 Javascript 浏览器引擎的工作(不要与浏览器引擎混同)。依据浏览器的不同,JS 引擎能够有不同的名称和不同的工作形式。

Javascript 引擎

javascript 引擎(有时也称为 ECMAScript 引擎)是一种在浏览器中执行(运行)Javascript 代码的软件,而不仅仅是零部件(例如,V8 引擎是 Node.js 环境的外围组件)。

JavaScript 引擎通常由 Web 浏览器供应商开发,每个次要浏览器都有一个。咱们说过,目前应用最多的浏览器是 Chrome、Safari、Edge 和 Firefox。每个都应用不同的 Javascript 引擎,它们是:

V8 V8 是 Google 的高性能 JavaScript 引擎。它是用 C++ 编写的,用于 Chrome 和 Node.js 等。它实现了 ECMAScript(一种 JavaScript 规范,旨在确保网页在不同 Web 浏览器之间的互操作性)和 WebAssembley。它实现了 ECMA-262。

JavaScriptCore JavaScriptCore 是 WebKit 的内置 JavaScript 引擎,它为 Safari 浏览器、邮件和 macOS 上应用的其余应用程序提供反对。它目前依照 ECMA-262 标准实现 ECMAScript。它也被称为 SquirrelFish 或 SquirrelFish Extreme。

Chakra Chakra 是微软为其 Microsoft Edge 网络浏览器和其余 Windows 利用程序开发的 Javascript 引擎。它实现了 ECMAScript 5.1,并且对 ECMAScript 6 有局部(一直减少的)反对。它是用 C++ 编写的。

SpiderMonkey SpiderMonkey 是 Mozilla 的 Javascript 和 WebAssembly 引擎。它是用 C++、Javascript 和 Rust 编写的,用于为 Firefox、Servo 和其余我的项目提供反对。

一开始,Javascript 引擎只是简略的解释器。咱们明天应用的古代浏览器可能执行称为即时 (JIT) 编译的性能,这是编译和解释的混合体。

编译

在编译过程中,一个称为 编译器 的软件将用高级语言编写的代码一次性转换为机器代码。创立一个 指标文件,该文件能够在任何机器上运行。采取这些步骤后,就能够执行代码了。

解释

在解释过程中,解释器逐行查看 Javascript 代码并立刻执行。没有进行编译,因而没有创立指标代码(代码的输入由解释器自身应用其外部机制创立)。旧版本的 Javascript 应用这种类型的代码执行。

即时编译( JIT Compilation )

即时编译是给定语言的解释器的一个个性,它试图同时利用编译和解释。是在纯编译期间,代码是在执行之前被编译,然而在 JIT 编译中,代码在执行时(在运行时)被编译。所以咱们能够说源代码是动静转换为机器代码的。较新版本的 Javascript 应用这种类型的代码执行。

JIT 编译的一个很重要的方面就是将源代码编译成以后正在运行的机器的机器码指令。这意味着生成的机器代码是针对正在运行的机器的 CPU 架构进行了优化。

简而言之,这三个过程能够总结为:

  • 编译器:编译代码
  • 解释器:运行代码
  • JIT 编译器:在运行代码时进行编译

明天,编译 解释 这两个术语之间的界线曾经变得十分含糊,因而这个主题能够进行宽泛的答辩。如果你想理解更多对于这些过程的信息,你能够浏览这篇对于 Mozilla Hacks for starters 的文章。

请留神,我提到了旧版本和新版本的 Javascript。不反对较新版本语言的浏览器将解释代码,而反对的浏览器将应用某些版本的 JIT 来执行代码(V8、Chakra JavaScriptCore 和 SpiderMonkey 引擎都应用 JIT)。事实上,只管 Javascript 是一种解释型语言(它不须要编译),但现在大多数浏览器都会应用 JIT 编译来运行代码,而不是纯正的解释型语言。

Javascript 代码是如何解决的

当 Javascript 代码进入 Javascript 引擎时,它首先被解析。这意味着代码被读取,并且在这种状况下,代码被转换为称为 形象语法树 (AST) 的数据结构。代码将被拆分成与语言相干的局部(如 functionconst 关键字),而后所有这些局部将构建形象语法树。

假如咱们有一个文件,其中蕴含一个只做一件事的程序,那就是定义一个变量:

const age = 25;

这就是这行非常简单的代码看起来像形象语法树的形式(我正在应用 @babel/parser-7.16.12):

如果你想将一些 Javascript 转换为形象语法树,你能够应用这个工具。编写变量后失去的 AST 实际上要大得多,在屏幕截图中暗藏了更多节点。

构建 AST 后,它会被翻译成机器代码并立刻执行,因为古代 Javascript 应用即时编译。这段代码的执行将由 Javascript 引擎实现,利用称为“调用堆栈”的货色。

调用堆栈是解释器(如 Web 浏览器中的 JavaScript 解释器)跟踪其在调用多个函数的脚本中的地位的机制——以后正在运行的函数以及从该函数中调用的函数等。

6. 创立可拜访(无障碍)树

除了咱们始终在探讨的所有这些树(DOM、CSSOM 和 AST)之外,浏览器还构建了一种称为 可拜访(无障碍)树 的货色。

Web 开发中的可拜访性(通常缩写为 A11y — 如“a”,而后是 11 个字符,而后是“y”)意味着让尽可能多的人可能应用网站,即便这些人的能力在某种程度上受到限制。对很多人来说,技术让事件变得更容易。对于残障人士,技术使事件成为可能。可拜访性意味着开发尽可能易于拜访的内容,无论集体的身材和认知能力以及他们如何拜访网络 (ACT)。

一般而言,残疾用户能够并且的确在应用具备各种辅助技术的网页。他们应用屏幕阅读器、放大镜、眼动追踪、语音命令等。为了让这些技术发挥作用,它们须要可能拜访页面的内容。因为他们无奈间接读取 DOM,因而 ACT 开始发挥作用。

可拜访性树是应用 DOM 构建的,稍后辅助设施将应用它来解析和解释咱们正在拜访的网页的内容。ACT 就像 DOM 的语义版本,每次 DOM 更新时它都会更新。每个须要裸露给辅助技术的 DOM 元素都会在 ACT 中有一个对应节点。在未构建 ACT 之前,屏幕阅读器无法访问内容。

要查看可拜访性树的理论的样子,您能够通过 Google Chrome 浏览器。关上调试器 (F12) 并转到“元素”选项卡。从那里,你能够在右侧抉择“辅助性能”窗格。

我去 Google 并查看了搜寻输出,这是我在“计算”属性下的“辅助性能”窗格中失去的:

应用语义 HTML 的重要性超出了本文的范畴,但作为开发人员,咱们都应该记住,咱们构建的网站应该可供所有心愿应用它们的人应用。如果您想浏览无关该主题的更多信息,能够在此处找到一篇对于 Web 可拜访性的很好的介绍性文章。据互联网协会无障碍拜访特地兴趣小组称,目前全世界有超过 13 亿人(约占世界人口的 15%)患有某种模式的残疾。

7. 渲染树

在解析阶段构建的树(DOM、CSSOM)被组合成一种叫做 渲染树 的货色。这用于计算最终将绘制到屏幕上的所有可见元素的布局。渲染树的目标是确保页面内容以正确的程序绘制元素。它将作为在屏幕上显示像素的绘画过程的输出。

DOM 和 CSSOM 是应用 HTML 和 CSS 文件创建的。这两个文件蕴含不同类型的信息,树的构造也不同,那么渲染树是如何创立的呢?

联合 DOM 和 CSSOM

  • 浏览器将开始在 DOM 树的根部 施展魔法并遍历每个可见节点。一些节点,如脚本或元标记是不可见的,因而它们被疏忽。还有一些节点会被 CSS 暗藏(例如 display: "none" 属性),它们也会被疏忽。咱们只对可见节点感兴趣,因为只有它们对屏幕上的输出有影响。
  • 对于在 DOM 中找到的每个可见节点,将在 CSSOM 中找到相应的规定并利用它们。

以上步骤的后果将是一个蕴含所有可见节点、内容和款式的 渲染树

布局(回流)阶段

渲染树蕴含无关显示哪些节点及其计算款式的信息,但不蕴含每个节点的尺寸或地位。

接下来须要做的是计算这些节点在设施视口(浏览器窗口内)内的确切地位及其大小。这个阶段称为布局(在 Chrome、Opera、Safari 和 Internet Explorer 中)或重排(在 Firefox 中),但它们的意思雷同。浏览器在渲染树的根部开始这个过程并遍历它。

回流步骤不会只产生一次,而是每次咱们更改 DOM 中影响页面布局的某些内容时,即便是局部更改,都会触发回流。从新计算元素地位的状况示例如下:

  • 在 DOM 中增加或删除元素
  • 调整浏览器窗口大小
  • 更改元素的宽度、地位或使其浮动

让咱们来看一个十分根本的 HTML 示例,其中内嵌了一些 CSS:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Reflow</title>
  </head>
  <body>
    <div style="width: 100%; height: 50%">
      <div style="width: 50%; height: 50%">This is the reflow stage!</div>
    </div>
  </body>
</html>

下面的代码只是说在视口内咱们应该有两个 div,其中第二个嵌套在第一个外面。父 div 占据视口宽度的 100% 和高度的 50%。第二个 div 占据父 div 的 50% 这看起来像这样:

这个过程的输入是一个 相似盒子的模型 ,它精确地捕捉了每个元素须要在屏幕上的地位及其大小。实现此步骤后,输入就能够传递到下一步,称为 绘画阶段

绘画(重绘)阶段

在浏览器决定哪些节点须要可见并计算出它们在视口中的地位后,就能够在屏幕上绘制它们(渲染像素)了。这个阶段也被称为 光栅化阶段,浏览器将在布局阶段计算的每个盒子转换为屏幕上的理论像素。

就像布局阶段一样,绘画阶段不会只产生一次,而是每次咱们扭转屏幕上元素的外观时。这些状况的例子是:

  • 扭转元素的轮廓
  • 扭转背景色彩
  • 扭转不透明度或可见性

绘画意味着浏览器须要将元素的每个视觉局部绘制到屏幕上,包含文本、色彩、边框、暗影和替换元素(如按钮和图像),并且须要超快地实现。为了确保重绘能够比初始绘制更快地实现,屏幕上的绘图通常被分解成几层。如果产生这种状况,则须要进行合成。

分层和合成

传统意义上,网络浏览器齐全依赖 CPU 来出现网页内容。但当初即便是最小的设施也有高性能的 GPU,所有大部分实现计划都围绕着 GPU 来寻求更好的体验。

合成是一种将页面的各个局部分成层的技术,别离绘制它们并在称为合成器线程的独自线程中合成为页面。当文档的各个局部绘制在不同的层中并互相重叠时,合成是必要的,以确保它们以正确的程序绘制到屏幕上并且内容被正确出现。

通常,只有特定的工作会被重定向到 GPU,而这些工作能够由合成器线程独自解决。

为了找出哪些元素须要在哪一层,主线程遍历布局树并创立层树。默认状况下,只有一层(这些层的实现形式因浏览器而异),但咱们能够找到会触发重绘的元素,并为每个元素创立一个独自的层。这样,重绘不应利用于整个页面,而且此过程将能够应用到 GPU

如果咱们想向浏览器提醒某些元素应该在一个独自的层上,咱们能够应用 will-change CSS 属性。实际上有一些特定的属性和元素示意新层的创立。其中一些是 <video><canvas> 和任何具备 CSS opacity 属性、3D transformwill-change 和其余一些属性的元素。这些节点连同它们的后辈将被绘制到它们本人的图层上。

谨记

下面探讨的两种操作,回流和重绘,都是低廉的,尤其是在像手机这样解决能力低的设施上。这就是为什么在解决 DOM 更改时咱们应该尝试优化它们(我将在我的 DOM 系列的将来一篇文章中具体探讨这一点)。有些动作只会触发重绘,有些动作会同时触发回流和重绘。

总结

以上蕴含了浏览器的外围工作原理,心愿对正在学习前端的你有所帮忙。当然,这并不是所有的内容,后续我还会始终更新这篇文章,从更多方面去探讨浏览器的工作原理。最初感激大家对本文的反对~欢送点赞珍藏,在评论区留下你的浅见 🌹🌹🌹

本文为翻译文,原文地址

正文完
 0