了解浏览器如何工作有什么意义?我们可以满怀信心地提高性能。 使用浏览器时,通常我们会打开一个 URL,与页面交互,并在获得所需内容后关闭选项卡。 用户和浏览器之间的整个交互过程分为三个阶段:
- 加载阶段 ( Loading stage ) --- 从我们输入 URL 时开始。
- 交互阶段 ( Interaction stage ) --- 当我们可以浏览、点击页面并与页面交互时就开始了。
- 关闭阶段 ( Closing stage ) - 当我们单击选项卡上的关闭按钮时开始。
Web前端优化主要集中在加载和交互阶段。 从导航到渲染阶段,最关键的优化点是DOM构建阶段。许多因素可能会阻碍 HTML 解析并延长整个渲染阶段。当这种情况发生时,我们作为用户,不得不盯着白色的屏幕一段时间。
DOM 构造阻塞
在上一篇文章中,我们专注于渲染阶段并跳过了 HTML 解析的一些细节。 HTML 文档不仅仅包含 HTML,还包括 CSS 样式和 JavaScript 文件。两者都可能阻止 DOM 构建并降低 Web 性能。
JavaScript 如何阻止 DOM 构建?
让我们从一个简单的例子开始,一个内联 JavaScript。
在示例中,脚本替换了元素的内部文本。它修改 DOM 树。
HTML 解析器负责"翻译"HTML 文档。当看到 JavaScript 脚本时,HTML 会停止解析 DOM 并立即执行它。执行完成后,HTML 解析器继续解析 HTML 文档的其余部分。 如果它是链接到 script 标签的 JavaScript 文件怎么办?
当再次看到链接的脚本文件时,HTML 解析器会停止 DOM 树构建。同时,渲染器进程与网络进程通信,请求从服务器下载 JavaScript 文件。当网络进程传递数据时,渲染器进程在继续解析 HTML 文件之前执行脚本。 除了浏览器执行 JavaScript 的时间之外,下载过程还增加了构建 DOM 树的时间。
CSS 如何阻止 DOM 构建?
CSS 不会阻碍 DOM 构建。与 JavaScript 结合时确实如此。
在这种情况下,HTML 中引用了 CSS 样式文件,JavaScript 修改了"styles.css"文件中的样式。 在执行 JavaScript 来修改样式之前,渲染器进程需要准备好计算样式。因此,HTML 解析器无法继续,直到 CSS 文件解析完成,并且 JavaScript 文件执行完成。
在开发网站的时候,我们的HTML文档中难免会有链接文件。 为了加速该过程,预加载扫描器在构建 DOM 树的同时快速扫描文档数据。如果预加载扫描程序发现任何链接文件(例如 CSS 和 JavaScript 文件),它会创建与网络进程的 IPC 连接并向服务器请求数据。 渲染器进程何时恢复 DOM 结构?这取决于下载时间最长的文件。 假设需要下载两个文件。一个文件需要 1 秒,另一个文件需要 3 秒。总共是3秒。
加载阶段的优化是为了减少下载时间
在构建 DOM 树时,最耗时的部分是下载链接文件和执行 JavaScript。
关键指标------往返延迟时间 ( round-trip delay time, RTD )
当谈到优化时,我们需要一个关键指标来衡量它,这样我们就知道解决方案是否有效。 往返延迟时间 (RTD) 或往返时间 (RTT) 是电信领域的通用术语,测量发送和接收信号所需的时间长度。 在我们的上下文中,时间测量在网络进程向服务器发送请求时开始,在收到服务器的完整确认时结束。 RTD 是完成此过程所需的总时间长度。 由于 TCP 的特性,数据是以块的形式发送的。以一个 CSS 文件为例,大小为0.1M。通过 HTTP 发送的每个分块数据包的大小通常约为 14KB。一个0.1M的文件被分成8个包。我们可以说 CSS 文件需要 8 RTD 才能完成。 下载两个文件怎么样?一个 CSS 文件为 9KB,因此下载需要 1 RTD。另一个 JavaScript 文件大小为 15KB,需要 2 RTD 才能完成下载。由于下载是并行进行的,因此总时间为 2 RTD。 这里的计算并不完全准确,因为我们忽略了 TCP 连接时间和服务器响应时间,但你明白了。 考虑到 RTD,现在我们可以讨论优化:
- 减少关键资源的数量
- 最小化关键资源的大小
减少关键资源的数量
关键资源有哪些?加载页面时需要任何 CSS 和 JavaScript 文件。没有它们,您的网站就会崩溃。 为了减少链接文件,我们可以将必要的 CSS 和 JavaScript 数据直接移动到 HTML 文件中,以避免下载过程。 如果某些链接的 JavaScript 文件不会改变 DOM 树和样式,请用"defer"和/或"async"标记它们,这样它们就不会阻止 DOM 构造。 当 DOM 准备好但在"DOMContentLoaded"事件之前执行延迟脚本。异步脚本独立于其他脚本和事件。一旦可用,它就会立即运行。 有些人认为,它有助于根据媒体查询将大型 CSS 文件分成较小的文件。这并不完全正确。即使查询返回 false,仍会下载带有附加到其 标记的媒体查询的样式表。只是内容不适用样式。因此,它不会减少下载请求。
减少关键资源的规模
文件大小越小意味着 RTD 越少。我们可以通过压缩CSS和JavaScript文件来实现。此外,大多数压缩工具都会删除数据中的注释,这有助于减小文件大小。