现代 CSS

关键渲染路径(CRP)

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

介绍Web页面解析时曾提到过:DOM树和CSSOM树结合在一起会构建出 Render Tree(渲染树),渲染树结合 Layout 绘制在屏幕上,从而展现出来。常常把这个过程称为 关键渲染路径(Critical Rendering Path)简称 CRP

也就是说,CRP 所用的时间直接决定了页面首次渲染页面的时间。即,通过优化关键渲染路径,可以显著缩短首次渲染页面的时间

如果我们要优化一个 Web 页面性能,那就必须对关键渲染路径中每一步中发生了什么,只有优化了关键路径才能彻底优化渲染性能。通过优化关键渲染路径,我们可以显著缩短首次渲染页面的时间。此外,了解关键渲染路径还可以构建高性能交互式应用打下基础。

特别声明,接下来内容中关于“关键渲染路径” 术语都将以其缩写字母 CRP 来替代!

什么是CRP

关键渲染路径(Critical Rendering Path),简称 CRP。是指 浏览器将Web代码(HTML、CSS 和 JavaScript)转换为屏幕上可显示的像素所经历的过程。它有几个阶段,其中一些阶段可以并行进行以节省时间,但有些部分必须按照顺序进行。用下图来描述这几个阶段:

  • 首先,一旦浏览器得到响应,它就开始解析它。当它遇到一个依赖关系时,它就会尝试下载它
  • 如果它是一个样式文件(CSS文件),浏览器就必须在渲染页面之前完全解析它(这就是为什么说CSS具有渲染阻碍性)
  • 如果它是一个脚本文件(JavaScript文件),浏览器必须: 停止解析,下载脚本,并运行它。只有在这之后,它才能继续解析,因为 JavaScript 脚本可以改变页面内容(特别是HTML)。(这就是为什么说JavaScript阻塞解析)
  • 一旦所有的解析工作完成,浏览器就建立了 DOM 树和CSSOM树。将它们结合在一起就得到了渲染树。
  • 倒数第二步是将渲染树转换为布局。这个阶段也被称为 重排
  • 最后一步是绘制。它涉及到根据浏览器在前几个阶段计算出来的数据对像素进行字面上的着色

把这几步放到渲染引擎渲染页面的过程中来,就能更清晰的认识到,CRP 会经过下面几个过程:

简单地说,CRP 的步骤:

  • 处理 HTML 标记并构建 DOM 树
  • 处理 CSS 标记并构建 CSSOM 树
  • 将 DOM 树和 CSSOM 树合并大一个渲染树
  • 根据渲染树来布局
  • 将各个节点绘制到屏幕上

注意:当 DOM 或者 CSSOM 发生变化的时候(JavaScript可以通过 DOM API 和 CSSOM API 对它们进行操作,从而改变页面视觉效果或内容)浏览器就需要再次执行上面的步骤。而且,这里每一个过程都在Web页面的解析一节中做过详细阐述,具体每个过程做了些什么,可以阅读 Web 页面的解析一节。

什么是优化 CRP

优化CRP 就是尽早尽快加载解析与首屏相关的 HTML、CSS 和 JavaScript,即 最大限度缩短执行 CRP 所有过程耗费的总时间。这样就能说快将内容渲染到屏幕上,此外还能缩短首次渲染后屏幕刷新的时间,即为交互内容实现更高的刷新率。也就是常说的,尽量减少白屏、灰屏时间和减少用户可交互时间。

分析 CRP 性能

欲要优化 CRP,就要了解 CRP 几个步骤中存在的陷阱 。在开始之前,我们先定义一下用来描述 CRP 的术语:

  • 关键资源:可能阻塞网页渲染的资源
  • CRP长度:获取所有关键资源所需的往返次数或总时间
  • 关键字节:实现网页首次渲染所需的总字节数,它是所有关键资源传送文件大小的总和

在开始深入分析 CRP 性能之前,需要先花点时间了解 CRP 长度,因为搞清楚了他更有利于我们后面的内容的理解。

CRP 长度 是指:

获取所有阻塞关键资源所需的往返次数。比如样式文件,JS文件;其中图片不属于关键资源,因为图片不会阻塞浏览器的渲染。

关于 CRP 中有几个关键的时间点:

  • domLoading:整个 CRP 的开始时间点
  • domInteractive:浏览器刚好构建完 DOM 的时间点
  • domContentLoaded:DOM 构建完,且没有任何样式会阻塞脚本允许的时间点。意思就是当没有脚本文件执行的时候,DOM 构建完成时就到达这个时间点(没有脚本不会存阻塞)。当有脚本文件要执行时,CSSOM 会阻塞脚本文件执行,此时要等到CSSOM完成才会到这个时间点。因此,当存在脚本文件的时候,一般 domContentLoaded 会往后推移许多
  • domCompelete:表示所有资源已经下载完成,包括图片、字体等,这个时间点将触 onload 事件

如下图所示:

接下来通过一些简单地示例来阐述如何对 CPR 进行分析。先从最简单的示例开始。

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <title>Critical Path: No Style</title>
    </head>
    <body>
        <p>Hello <span>web performance</span> students!</p>
        <div><img src="awesome-photo.jpg"></div>
    </body>
</html>

上面这个HTML文档是个最基础的HTML文档,<body> 中只有一个 <p><span><div><img> (网页内容只有一行文本和一张图片),没有任何的 CSS 和 JavaScript。使用 Chrome DevTools 打开 “Network” 选项,并检查生成的资源瀑布:

如上图所示,HTML 文件下载花费了大约 400ms (不同环境不同时候测试结果可能会有所差异)。

上图描述了 basic_dom_nostyle.html 文件从发起网格请求到得到响应以及完成下载的时间。该文件自身下载量很小(大约 6.3kB),我们只需要单次往返便可获取整个文件。因此,获取 HTML 文档大约花了 380ms ,其中等待的时间就花了差不多 370ms

当HTML内容可用后,浏览器会解析字节,将它转换成令牌,然后构建 DOM 树。为了方便起见,DevTools 会在底部报告 DOMContentLoaded 事件的时间(399ms),该时间与蓝色垂直线相符。 HTML 下载结束与蓝色垂直线(DOMContentLoaded)之间的间隔是浏览器构建 DOM 树所花费的时间。

请注意,我们的“趣照”并未阻止 DOMContentLoaded 事件。这证明, 我们构建渲染树甚至绘制网页时无需等待页面上的每个资产,即 并非所有资源都对快照提供首次绘制具有关键作用。事实上,当我们谈论起 CRP 时,通常谈论的是 HTML、CSS 和 JavaScript。 图像不会阻止页面的首次渲染,不过,我们也应该尽力确保系统尽快绘制图像!

即便如此,系统还是会阻止图像上的 load 事件(也称 onload),上面示例中,DevTools 显示的 load 事件时间大约在 616ms 时发生。回想一下,onload 事件标记的点是网页所需的 所有资源 均已下载并经过处理的点,这是加载微调框可以在浏览器中停止微调的点(由瀑布中的红色垂直线标记)。

这也是 CRP 性能模式中最简单的一种(页面只有 HTML 标记,没有 CSS 和 JavaScript)。要渲染此类网页,浏览器需要 发起请求,等待 HTML 文档到达,对其进行解析,构建 DOM,最后将其渲染到屏幕上

T0与T1之间的时间捕获的是网络和服务器处理时间。在最理想的情况下(如果 HTML 文件较小),只需要一次网格往返便可获取整个文档。由于 TCP 传输协议工作方式的缘故,较大文件可能要更多次往返。 因此,在最理想的情况下,上述网页具有单次往返最少 CRP

  • 关键资源:1个(html)
  • 关键路径资源大小:5KB(html)
  • CRP长度:1次(获取html文件最少网格往返)

接下来,我们在上面的示例基础上引入一个外部资源,即在</head> 前引入一个外部的style.css文件:

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <link href="style.css" rel="stylesheet">
    </head>
    <body>
        <p>Hello <span>web performance</span> students!</p>
        <div><img src="awesome-photo.jpg"></div>
    </body>
</html>

在这个示例中,从“Ne

剩余80%内容付费后可查看
返回顶部