浏览器如何加载网站

在上一篇文章中,我们概述了构建网站的技术。在本文中,我们将介绍这些技术的渲染过程——当浏览器收到构成网页的代码文件和其他资产(如Web 如何工作中所述)后,它们是如何组合在一起以创建用户交互的最终体验的?

预备知识 熟悉您的计算机操作系统、Web 浏览器和 Web 技术的基本知识。
学习成果
  • HTTP 响应中返回的不同类型的资产。
  • 浏览器如何组装不同的文件以渲染网页并将其显示给用户。
  • 为什么浏览器有时被视为一个“充满敌意”的编程环境,但同时也是一个很棒的编程环境。

HTTP 响应中返回哪些文件?

总结一下我们在上一篇文章中看到的Web 技术概述,HTTP 响应(对网页请求)通常会包含以下一些文件类型

  • HTML 文件,用于指定网页内容及其结构。
  • CSS 文件,用于指定样式和布局信息。
  • JavaScript 文件,用于指定网页交互部分的行为。
  • 媒体资产,例如图像、视频、音频文件、PDFSVG,它们嵌入在网页中或由浏览器显示。
  • 浏览器无法本地处理的其他类型文件,因此将其交给设备上的相关应用程序进行渲染,例如 Word 或 Pages 文档、PowerPoint 幻灯片演示和 Open Office 文件。

网页渲染

当用户导航到新网页时(通过点击链接或在浏览器地址栏中输入网址),会发送多个 HTTP 请求,并在 HTTP 响应中返回多个文件。这些响应中收到的文件由浏览器处理并组合成一个用户可以交互的网页。将这些部分组装成网页的过程称为渲染

以下部分将高级解释浏览器如何渲染网页。请记住,这是一个简化的描述,不同的浏览器将以不同的方式处理该过程。但是,这仍然能让您对事情的工作方式有所了解。

处理 HTML

首先,浏览器会接收并解析包含网页内容并定义其结构的 HTML 文件。浏览器将其转换为树状结构,称为 DOM 树文档对象模型)。DOM 代表计算机内存中的 HTML 文档结构。以这个基本的 HTML 片段为例

html
<p>
  Let's use:
  <span>HTML</span>
  <span>CSS</span>
  <span>JavaScript</span>
</p>

HTML 中的每个元素、属性和文本片段都成为树结构中的一个 DOM 节点。节点由它们与其他 DOM 节点的关系定义。有些元素是子节点的父节点,子节点有兄弟节点。浏览器将解析此 HTML 并从中创建以下 DOM 树

P
├─ "Let's use:"
├─ SPAN
|  └─ "HTML"
├─ SPAN
|  └─ "CSS"
└─ SPAN
    └─ "JavaScript"

在此 DOM 树中,对应于我们 <p> 元素的节点是父节点。它的子节点包括一个文本节点和对应于我们三个 <span> 元素的三个节点。SPAN 节点也是父节点,其子节点是文本节点。当浏览器渲染此 DOM 树时,它将如下所示

某些 HTML 元素在解析时会触发更多 HTTP 请求

解析 CSS 和渲染页面

接下来,处理 CSS。

  1. 浏览器会解析页面中找到的 CSS(无论是包含在 HTML 文件中,还是从外部样式表中获取),并根据它们将应用于哪些 HTML 元素(在 DOM 中表示为称为节点的项目)将不同的 CSS 样式规则分类到不同的“桶”中。然后,浏览器会根据需要将样式附加到不同的元素(此中间步骤称为渲染树)。
  2. 渲染树按照规则应用后应出现的结构进行布局。这包括任何要嵌入页面中的图像和其他媒体文件。
  3. 页面的视觉显示呈现在屏幕上(此阶段称为绘画)。

下图展示了我们目前所讨论过程的可视化

Rendering process overview

回到我们的例子,假设在 HTML 文件中找到以下 CSS

css
span {
  border: 1px solid black;
  background-color: lime;
}

CSS 中唯一的规则有一个 span 选择器,所以浏览器可以非常快速地对 CSS 进行分类!它将该规则应用于 DOM 树中的每个 SPAN 节点,给它们一个黑色边框和石灰绿色背景,然后将最终的视觉表示绘制到屏幕上。

更新后的输出如下

处理 JavaScript

处理完 CSS 后,页面中找到的任何 JavaScript(无论是包含在 HTML 文件中,还是从外部脚本文件中获取)都会被解析、解释、编译和执行。这发生在最终页面渲染完成之前的某个时刻——毕竟,一些 JavaScript 可能会影响渲染,例如通过向 DOM 添加节点或修改现有节点。

回到我们的例子,假设在 HTML 文件中找到以下 JavaScript

js
const spans = document.querySelectorAll("span");
spans.forEach((span) => {
  const reversedText = span.textContent.split("").reverse().join("");
  span.textContent = reversedText;
});

您不需要完全理解此 JavaScript 的工作原理,但在高层次上,它会查找 DOM 中每个 SPAN 节点并反转其子文本节点中字符的顺序。

最终输出如下

还有哪些渲染步骤?

在页面渲染过程中还会发生其他一些事情,但我们不会在这里全部讨论。值得一提的一个显著的额外事件是,会根据 DOM 构建一个辅助功能树,供辅助技术(例如屏幕阅读器)接入,这使得无法看到渲染内容的人也能够与之交互。

您将在稍后的辅助功能模块中了解更多信息。

浏览器:一个“充满敌意”一个很棒的编程环境

前端 Web 开发有时会令人沮丧,有些人认为浏览器是一个“充满敌意”的编程环境。这是因为,与其他编程环境不同,它更难保证代码运行的环境。您无法提前知道用户将拥有的操作系统、浏览器、语言、位置、网络连接、CPU、GPU、内存、电池寿命等所有不同组合,因此您无法保证所有用户都能获得完美的体验。

现代浏览器倾向于相当一致地实现 Web 标准,但仍有许多不确定性需要应对。作为 Web 开发人员,您需要接受这种不确定性,进行防御性编程,并保守地使用功能。这取决于遵守上一篇文章中概述的最佳实践

从积极的一面来看,Web 也是一个很棒的编程环境,原因有很多。

  • 首先,它的设计考虑到了通用访问。Web 的基本状态是可访问和可链接的。其中一些基本功能在其他环境中更难实现。
  • Web 上的应用程序交付既简单又强大。您无需让用户经历复杂的安装过程:只需将他们指向一个网址,他们就可以开始使用。
  • 应用程序更新通常很简单。在许多情况下,访问者在重新加载浏览器选项卡时可以看到应用程序的新版本。您无需担心让访问者定期下载和安装软件更新。
  • Web 社区充满活力且乐于助人。正如我们稍后在研究和学习文章中讨论的那样,有很多地方可以寻求帮助,也有很多很棒的资源可以学习。

另见

何时以及如何向浏览器报告 bug

如果浏览器中某个功能未按预期工作,则可能是浏览器 bug。本文解释了如何确定是否是 bug,以及如果是 bug 如何提交 bug 报告。