性能优化之关键渲染路径

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 分别从浏览器架构和最新的渲染引擎介绍了关于页面渲染的相关概念。对应连接如下。• 页面是如何生成的(宏观角度)• Chromium 最新渲染引擎--RenderingNG• RenderingNG中关键数据结构及其角色而今天的主角是{关键渲染路径| Critical Rendering Path}。它是影响页面在加载阶段的主要标准。


不要再问**“那怎么可能”,而是问“为什么不能”**

大家好,我是柒八九

今天,我们来谈谈,浏览器的关键渲染路径。针对浏览器的一些其他文章,我们前面有介绍。分别从浏览器架构最新的渲染引擎介绍了关于页面渲染的相关概念。对应连接如下。

而今天的主角是{关键渲染路径| Critical Rendering Path}。它是影响页面在加载阶段的主要标准。

这里再啰嗦一点,通常一个页面有三个阶段

  1. 加载阶段
  • 是指从发出请求到渲染出完整页面的过程
  • 影响到这个阶段的主要因素有网络JavaScript 脚本
  1. 交互阶段
  • 主要是从页面加载完成到用户交互的整个过程
  • 影响到这个阶段的主要因素是 JavaScript 脚本
  1. 关闭阶段
  • 主要是用户发出关闭指令后页面所做的一些清理操作

好了,时间不早了。开干。

能所学到的知识点

  1. 关键渲染路径的各种指标
  2. {关键资源| Critical Resource}:所有可能阻碍页面渲染的资源
  3. {关键路径长度|Critical Path Length}:获取构建页面所需的所有关键资源所需的 RTT(Round Trip Time)
  4. {关键字节| Critical Bytes}:作为完成和构建页面的一部分而传输的字节总数
  5. 重温HTTP缓存
  6. 针对关键渲染路径进行各种优化处理
  7. 针对React应用做优化处理

1. 加载阶段关键数据

{文档对象模型| Document Object Model}

DOM:是HTML页面在解析后,基于对象的表现形式。

DOM是一个应用编程接口(API),通过创建表示文档的树,以一种独立于平台和语言的方式访问和修改一个页面的内容和结构。

HTML 文档中,Web开发者可以使用JS来CRUD DOM 结构,其主要的目的是动态改变HTML文档的结构。

DOM 将整个HTML页面抽象为一组分层节点

DOM 并非只能通过 JS 访问, 像{可伸缩矢量图| SVG}{数学标记语言| MathML}{同步多媒体集成语言| SMIL}都增加了该语言独有的 DOM 方法和接口。

一旦HTML被解析,就会建立一个DOM树

下面的代码有三个区域:headermainfooter。并且style.css外部文件

<html>
  <head>
      <link rel="stylesheet" href="style.css">
      <title>关键渲染路径示例</title>
  </head>
  <body>
    <header>
      <h1>...</h1>
      <p>...</p>
    </header>
    <main>
         <h1>...</h1>
         <p>...</p>
    </main>
    <footer>
         <small>...</small>
    </footer>
  </body> 
</html>
复制代码

当上述 HTML 代码被浏览器解析为 DOM树状结构时,其各个节点的关系如下。

每个浏览器都需要一些时间解析HTML。并且,清晰的语义标记有助于减少浏览器解析HTML所需的时间。(不完整或者错误的语义标记,还需要浏览器根据上下文去分析和判断)

具体,浏览器是如何将HTML字符串信息,转换成能够被JS操作的DOM对象,不在此文的讨论范围内。不过,我们可以举一个很小的例子。在我们JS算法探险之栈(Stack)中,有一个题就是如何判断括号的正确性

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。 有效字符串需满足:

左括号必须用相同类型的右括号闭合。

左括号必须以正确的顺序闭合。

示例:

输入:s = "()[]{}" 输出:true

输入:s = "(]" 输出:false

其实,上面的例子就是最简单的一种标签匹配。或者说的稳妥点,它们的主要思想是一致的。


CSSOM Tree

CSSOM也是一个基于对象的树。它负责处理与DOM树相关的样式

承接上文,我们这里有和上面HTML配套的CSS样式。

header{
   background-color: white;
   color: black;
}
p{
   font-weight:400;
}
h1{
   font-size:72px;
}
small{
   text-align:left
}
复制代码

对于上述CSS声明,CSSOM树将显示如下。

由于,css的部分属性能够被继承,所以,在父级节点定义的属性,如果满足情况,子节点也是会有对应的属性信息,最后将对应的样式信息,渲染到页面上。

一般来说,CSS被认为是一种{渲染阻断| Render-Blocking}资源。

什么是渲染阻断?渲染阻塞资源是一个组件,它将不允许浏览器渲染整个DOM树,直到给定的资源被完全加载

CSS 是一种渲染阻断资源,因为在CSS完全加载之前,你无法渲染树。

起初,页面中所有CSS信息都被存放在一个文件中 。现在,开发人员通过一些技术手段,能够将CSS文件分割开来,只在渲染的早期阶段提供关键样式


执行JS

先将一个小知识点,其实,在前面的文章中,我们已经讲过了。这里,我们再啰嗦一遍。

浏览器环境下JS = ECMAScript + DOM + BOM

ECMAScript

JS的核心部分,即 ECMA-262 定义的语言,并不局限于 Web 浏览器。

Web 浏览器只是 ECMAScript 实现可能存在的一种{宿主环境| Host Environment}。而宿主环境提供 ECMAScript基准实现和与环境自身交互必需的扩展。(比如 DOM 使用 ECMAScript 核心类型和语法,提供特定于环境的额外功能)。

像我们比较常见的Web 浏览器Node.js和已经被淘汰的 Adobe Flash都是ECMA的宿主环境。

ECMAScript 只是对实现ECMA-262规范的一门语言的称呼, JS 实现了 ECMAScriptAdobe ActionScript 也实现 ECMAScript

上面的内容只是做一个知识点的补充,我们这篇文章中出现的JS还是一般意义上的含义:即javascript文本信息。


JavaScript 是一种用来操作DOM的语言。这些操作花费时间,并增加网站的整体加载时间。所有,

JavaScript 代码被称为 {解析器阻塞| Parser Blocking}资源。

什么是解析器阻塞?当需要下载执行JavaScript代码时,浏览器会暂停执行和构建DOM树。当JavaScript代码被执行完后,DOM树的构建才继续进行。

所以才有, JavaScript是一种昂贵的资源的说法。


示例演示

下面是一段HTML代码的演示结果,显示了一些文字和图片。正如你所看到的,整个页面的显示只花了大约40ms。即使有一张图片,页面显示的时间也更短。这是因为在进行第一次绘制时,图像没有被当作关键资源

记住,

{关键渲染路径| Critical Rendering Path}都是关于HTMLCSSJavascript

现在,在这段代码中添加css。正如下图所示,一个额外的请求被触发了。尽管加载html文件的时间减少了,但处理和显示页面的总体时间却增加了近10倍。为什么呢?

  • 普通的HTML并不涉及太多的资源获取解析工作。但是,对于CSS文件,必须构建一个CSSOMHTMLDOMCSSCSSOM 都必须被构建。这无疑是一个耗时的过程。
  • JavaScript 很有可能会查询 CSSOM。这意味着,在执行任何JavaScript之前,CSS文件必须被完全下载和解析

注意domContentLoadedHTML DOM完全解析和加载时被触发。该事件不会等待image、子frame甚至是样式表被完全加载。唯一的目标是文档被加载。可以在window中添加事件,以查看DOM是否被解析和加载。

window.addEventListener('DOMContentLoaded', (event) => {
    console.log('DOM被解析且加载成功');
});
复制代码

即使你选择用内联脚本取代外部文件,性能也不会有大的改变。主要是因为需要构建CSSOM。如果你考虑使用外部脚本,可以添加 async属性。这将解除对解析器的阻断


关键路径相关术语

  • {关键资源| Critical Resource}:所有可能阻碍页面渲染的资源
  • {关键路径长度|Critical Path Length}:获取构建页面所需的所有关键资源所需的RTT(Round Trip Time)
  • 当使用 TCP 协议传输一个文件时,由于 TCP 的特性,这个数据并不是一次传输到服务端的,而是需要拆分成一个个数据包来回多次进行传输的
  • RTT就是这里的往返时延
  • 它是网络中一个重要的性能指标表示从发送端发送数据开始,到发送端收到来自接收端的确认,总共经历的时延
  • 通常 1 个HTTP的数据包在14KB左右
  • 首先是请求 HTML 资源,假设大小是 6KB,小于 14KB,所以 1 个 RTT 就可以解决
  • 至于JavaScriptCSS文件
  • 由于渲染引擎有一个预解析的线程,在接收到 HTML 数据之后,预解析线程会快速扫描 HTML 数据中的关键资源,一旦扫描到了,会立马发起请求
  • 可以认为 JavaScriptCSS同时发起请求的,所以它们的请求是重叠的,计算它们的 RTT 时,只需要计算体积最大的那个数据就可以了
  • {关键字节| Critical Bytes}:作为完成和构建页面的一部分而传输的字节总数

在我们的第一个例子中,如果是普通的HTML脚本,上面各个指标的值如下

  • 1个关键资源(html)
  • 1个RTT
  • 192字节的数据

在第二个例子中,一个普通的HTML和外部CSS脚本,上面各个指标的值如下

  • 2个关键资源(html+css)
  • 2个RTT
  • 400字节的数据

如果你希望优化任何框架中的关键渲染路径,你需要在上述指标上下功夫并加以改进。

  • 优化关键资源
  • JavaScriptCSS 改成内联的形式 (性能提升不是很大)
  • 如果 JavaScript 代码没有 DOM 或者 CSSOM 的操作,则可以改成 sync 或者 defer 属性
  • 首屏内容可以优先加载,非首屏内容采用滚动加载
  • 优化关键路径长度
  • 压缩CSSJavaScript 资源
  • 移除 HTMLCSSJavaScript 文件中一些注释内容
  • 优化关键字节
  • 通过减少关键资源的个数和减少关键资源的大小搭配来实现
  • 使用 CDN 来减少每次 RTT 时长

减少渲染器阻塞资源

懒加载

加载的关键是 "懒加载"。任何媒体资源、CSSJavaScript、图像、甚至HTML都可以被懒加载。每次加载有限的页面的内容,可以提高关键渲染路径。

  • 不要在加载页面时加载这个整个页面的 CSSJavaScriptHTML
  • 相反,可以为一个button添加一个事件监听,只有在用户点击按钮时才加载脚本。
  • 使用Webpack来完成懒加载功能。

这里有一些利用纯JavaScript实现懒加载的技术。

比如,现在又一个/

相关文章
|
6月前
|
前端开发 JavaScript UED
如何优化前端网页加载速度:最佳实践与技巧
本文探讨了如何通过优化前端网页加载速度来提升用户体验和网站性能。从资源压缩和合并、减少HTTP请求、优化图片、使用CDN加速、采用异步加载和延迟加载等方面介绍了一系列最佳实践和技巧,帮助开发者更好地优化前端性能,提升网页加载速度。
|
3月前
|
缓存 前端开发 网络协议
性能优化|几个方法让图片加载更快一些
对电商网页的性能而言,图片优化是至关重要的事情,本文就此探讨了一些简单、可靠的图片优化手段。
|
3月前
|
前端开发 JavaScript UED
现代前端开发中的动态组件加载与性能优化
传统的前端应用加载所有组件可能会导致性能问题和用户体验下降。本文讨论了现代前端开发中采用动态组件加载的策略,通过异步加载和按需渲染优化页面加载速度和资源利用效率。
|
前端开发 JavaScript Serverless
前端工程化的前端性能的性能优化方案的渲染层面优化之CSS/JS优化
渲染是一种非常重要的前端性能优化方案,因为它可以在不同的环境中提高网页的响应速度和可接受性。
88 2
|
前端开发 Serverless 开发者
前端工程化的前端性能的性能优化方案的渲染层面优化之懒加载
懒加载是一种非常重要的前端性能优化方案,因为它可以在不同的环境中提高网页的响应速度和可接受性。
88 0
|
移动开发 前端开发 JavaScript
前端工程化的前端性能的性能优化方案的渲染层面优化之DOM优化
DOM 优化是一种非常重要的前端性能优化方案,因为它可以在不同的环境中提高网页的响应速度和可接受性。
86 0
|
缓存 JavaScript 前端开发
【 Vue3 性能优化】页面加载性能 与 更新性能
【 Vue3 性能优化】页面加载性能 与 更新性能
936 0
|
JavaScript 前端开发 大数据
虚拟滚动是怎么做性能优化的?
虚拟滚动是怎么做性能优化的?
280 0
|
存储 缓存 前端开发
浅谈性能优化之图片压缩、加载和格式选择
目前市场上优化图片资源的方式有很多,如压缩图片、选择正确格式、 CDN 加速、懒加载等。
264 0
浅谈性能优化之图片压缩、加载和格式选择
|
移动开发 缓存 前端开发
客户端内H5页面的首屏性能优化
客户端内H5页面的首屏性能优化
497 0
客户端内H5页面的首屏性能优化