我们打造效果数据分析的方式和原因

Chrome 102 中,您会在开发者工具中看到一个新的实验性面板:性能数据分析。在本文中,我们不仅会讨论我们为何开发新的面板,还会介绍我们面临的技术挑战以及在此过程中做出的决策。

ALT_TEXT_HERE

为什么要构建另一个面板?

(如果您尚未观看,我们发布了一个视频,介绍了为何要构建“效果分析”面板,以及如何通过该面板获得有关网站效果的实用数据洞见。)

如果您希望在一个位置集中查看自己网站的所有数据,现有的效果面板是非常实用的资源,但我们认为这样可能让您应接不暇。如果您不是性能专家,就很难准确知道要查找什么,以及录制的哪些部分与问题相关。

进入“洞察”面板后,您仍然可以查看轨迹的时间轴并检查数据,还可以查看 DevTools 认为值得深入探究的主要“洞察”的便捷列表。数据分析将找出渲染阻塞请求、布局偏移和长任务等问题,这些问题都可能会对您网站的网页加载性能产生负面影响,尤其是对您网站的核心网页指标 (CWV) 得分。除了标记问题之外,效果分析还会为您提供切实可行的建议来帮助您提高 CWV 得分,并提供指向更多资源和文档的链接。

面板中的反馈链接

此面板目前处于实验阶段,我们期待收到您的反馈!如果您遇到任何错误,或提出您认为有助于提升网站性能的功能请求,请告知我们。

内容表现数据分析的构建过程

与其他开发者工具一样,我们使用 TypeScript 构建了性能分析,并使用由 lit-html 支持的Web 组件构建了界面。效果分析的不同之处在于,主要界面是 HTML canvas 元素,时间轴会绘制到此画布上。很多复杂性都来自于管理此画布:不仅要在正确的位置绘制正确的详细信息,还要管理鼠标事件(例如:用户在画布上点击了哪里?他们是否点击了我们绘制的活动?)并确保我们有效地重新渲染了画布。

在单个画布上添加多个轨道

对于给定的网站,我们希望呈现多个“轨道”,每个轨道代表一类不同的数据。例如,“数据分析”面板默认会显示三个轨道:

随着我们不断在信息面板中推出功能,预计还会添加更多轨道。

我们最初的想法是让这些轨道各自渲染自己的 <canvas>,以便主视图变成垂直堆叠的多个画布元素。这会简化轨道级渲染,因为每个轨道都可以单独渲染,并且不会有轨道渲染超出其边界的危险,但遗憾的是,这种方法存在两个主要问题:

canvas 元素的(重新)渲染开销很高;使用多个画布比使用一个画布开销更高,即使该画布更大也是如此。 渲染跨多个轨道的任何叠加层(例如用于标记 FCP 时间等事件的垂直线条)变得复杂:我们必须渲染到多个画布上,并确保它们一起渲染并正确对齐。

为整个界面使用一个 canvas 意味着,我们需要弄清楚如何确保每个轨道都渲染在正确的坐标处,并且不会溢出到其他轨道。例如,如果某个轨道的高度为 100 像素,我们就不能允许它渲染高度为 120 像素的内容,并使其溢出到下方的轨道。为解决此问题,我们可以使用 clip。在呈现每个轨道之前,我们会绘制一个矩形来表示可见的轨道窗口。这样可确保在这些边界之外绘制的所有路径都会被画布剪裁。

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

我们还不希望每个轨道都必须知道其垂直位置:每个轨道都应像在 (0, 0) 处渲染一样进行自我渲染,并且我们使用更高层级的组件(我们称之为 TrackManager)来管理总体轨道位置。这可以通过 translate 来实现,它会将画布沿给定的 (x, y) 位置平移。例如:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

尽管 rect 代码将 0, 0 设置为位置,应用的整体平移将导致矩形在 0, 10 处渲染。这样,我们就可以按轨道进行操作,就像在 (0, 0) 处进行渲染一样,并让轨道管理器在渲染每个轨道时进行转换,以确保每个轨道都正确地渲染在前一个轨道下方。

用于呈现曲目和精彩集锦的屏幕外画布

Canvas 渲染相对较耗资源,因此我们希望确保您在使用“数据分析”面板时,该面板始终保持流畅和快速响应。有时,您无法避免重新渲染整个画布:例如,如果您更改缩放级别,我们必须重新开始,并重新渲染所有内容。画布重新渲染的成本特别高昂,因为您实际上无法只重新渲染一小部分画布,而是需要擦除整个画布并重新绘制。这与 DOM 重新渲染不同,在 DOM 重新渲染中,工具可以计算所需的最少工作量,而不会移除所有内容并重新开始。

我们在视觉效果方面遇到的一个问题是突出显示。当您将鼠标悬停在该窗格中的指标上时,我们会在时间轴上突出显示这些指标;同样,如果您将鼠标悬停在特定事件的分析洞见上,我们会在该事件周围绘制蓝色边框。

此功能最初的实现方式是,检测鼠标在触发突出显示的元素上移动,然后直接将突出显示内容绘制到主画布上。问题在于,当我们必须移除突出显示的内容时,唯一的选择是重新绘制所有内容!我们不可能仅重新绘制突出显示区域(除非进行重大架构更改),但仅仅因为要移除某个项周围的蓝色边框而重新绘制整个画布似乎有些过度。如果您快速将鼠标移动到不同的项上,以快速触发多个突出显示,则视觉上也会出现延迟。

为了解决此问题,我们将界面拆分为两个屏幕外画布:“主”画布(轨道渲染到此处)和“亮点”画布(绘制亮点)。然后,我们通过将这些画布复制到用户可在屏幕上看到的单个画布上进行渲染。我们可以在画布上下文上使用 drawImage 方法,该方法可以将另一个画布作为其来源。

这样一来,移除突出显示内容不会导致重新绘制主画布:我们可以清除屏幕上的画布,然后将主画布复制到可见的画布上。复制画布的操作成本低廉,而绘制的成本也很高;因此,通过将高光移动到单独的画布上,我们可以避免在打开和关闭高光时产生这些开销。

全面测试的轨迹解析

从头开始构建新功能的好处之一是,您可以反思之前做出的技术选择并进行改进。我们想要改进的一项内容是,明确将代码拆分为两个几乎完全不同的部分:

解析轨迹文件并提取所需数据。 渲染一组轨道。

将解析(第 1 部分)与界面工作(第 2 部分)分开,使我们能够构建一个可靠的解析系统;每个轨迹都通过一系列负责不同问题的处理程序运行:LayoutShiftHandler 会计算我们需要的有关布局偏移的所有信息,NetworkRequestsHandler 则专门负责提取网络请求。通过这种明确的解析步骤,我们可以让不同的处理程序负责跟踪的不同部分,这也有助于我们一次专注于一个问题。

我们还能够在 DevTools 中进行录制、保存录制内容,然后将其作为测试套件的一部分加载,从而全面测试轨迹解析。这非常棒,因为我们可以使用真实轨迹进行测试,而不会积累可能过时的大量虚假轨迹数据。

画布界面的屏幕截图测试

继续谈谈测试,我们通常会通过将前端组件呈现到浏览器中并确保其行为符合预期来测试这些组件;我们可以调度点击事件以触发更新,并断言组件生成的 DOM 是正确的。这种方法很适合我们,但在考虑渲染到画布时却失败了;无法检查画布并确定在此处绘制的内容!因此,我们通常的渲染后查询方法不适用。

为了进行一些测试,我们采用了屏幕截图测试。每项测试都会启动一个画布,渲染我们要测试的轨道,然后截取画布元素的屏幕截图。然后,此屏幕截图会存储在我们的代码库中,日后运行的测试将会将存储的屏幕截图与其生成的屏幕截图进行比较。如果屏幕截图不同,测试将失败。我们还提供了一个标志,用于在我们有意更改渲染并需要更新测试时运行测试并强制更新屏幕截图。

屏幕截图测试并不完美,而且有点粗糙;您只能测试整个组件是否按预期呈现,而无法进行更具体的断言。起初,我们过度使用了屏幕截图测试,以确保每个组件(HTML 或画布)都正确呈现。这极大地降低了测试套件的速度,并导致了一些问题:几乎无关紧要的细微界面调整(例如细微的颜色更改或在项之间添加一些边距)会导致多个屏幕截图失败并需要更新。我们现在已减少屏幕截图的使用,仅将其用于基于画布的组件,这种平衡到目前为止对我们来说效果很好。

总结

构建新的“效果数据分析”面板对团队来说是一次非常愉快且富有启发性的体验。我们已经学习了许多关于轨迹文件、使用画布等内容。希望您喜欢使用新版控制台,我们也期待收到您的反馈。

如需详细了解“效果数据分析”面板,请参阅效果数据分析:获取有关网站性能的实用数据分析

下载预览渠道

不妨考虑将 Chrome Canary 版开发者版Beta 版用作默认开发浏览器。通过这些预览版渠道,您可以使用最新的 DevTools 功能、测试尖端的 Web 平台 API,并帮助您在用户发现问题之前发现网站上的问题!

与 Chrome 开发者工具团队联系

使用以下选项讨论新功能、更新或与开发者工具相关的任何其他内容。