诊断强制同步布局(Layout)

优质
小牛编辑
130浏览
2023-12-01

了解如何使用DevTools诊断强制同步布局。

在本指南中,您通过一个demo来识别和解决问题,了解如何调试强制同步布局。 演示动画图像使用requestAnimationFrame(), 这是基于帧的动画的推荐方法。 然而,在动画中有相当多的卡顿。你的目标是确定卡顿的原因并解决这个问题,让demo中的动画能够达到顺滑的60 FPS。

1.png

收集数据

首先,您需要收集数据,以便您可以准确了解页面运行时会发生什么。

  1. 打开演示页面。
  2. 打开DevTools的Timeline(时间轴)面板。
  3. 启用JS Profile(JS分析)文件选项。当后面分析火焰图时,此选项将让您准确查看调用的函数。
  4. 点击页面上的Start(开始)按钮以启动动画。
  5. 点击Timeline(时间轴)面板上的Record(录制)按钮以开始时间轴录制。
  6. 等待几秒钟。
  7. 再次点击Record(录制)按钮,停止录制。

录制完成后,您应该在Timeline(时间轴)面板上看到类似下面的内容。

2.png

识别问题

现在你有你的数据,是时候开始理解它了。

乍看上去,您可以在Timeline(时间轴)录制的Summary(摘要)窗格中看到浏览器在rendering(渲染)上花了大部分时间。一般来说,如果您可以优化页面的layout(布局)操作,就可以减少rendering(渲染)花费的时间。

3.png

现在将注意力移到Overview(概览)窗格正下方的粉红色时间条。时间条代表帧。将鼠标悬停在他的上面,可以查看有关该帧的更多信息。

4.png

这些帧需要很长时间才能完成。为了平滑的动画,帧频率需要达到60 FPS。

现在是时候诊断究竟是哪里有问题。使用鼠标,放大调用栈。

5.png

栈的顶部是Animation Frame Fired(动画帧触发)事件。只要触发此事件,就会调用传递给requestAnimationFrame()的函数。在Animation Frame Fired(动画帧触发)你看到Function Call(函数调用),和下面你看到update。你可以推断一个名为update()的方法是requestAnimationFrame()的回调。

注意: 这是您之前启用JS Profile(JS分析)选项有用的地方。如果它被禁用,你只会看到`Function Call`(函数调用),然后是所有小的紫色事件(下面讨论),没有关于确切地调用哪些函数的详细信息(注:看不到具体是哪个函数被调用了)。

现在,将注意力集中在update事件下面的所有小的紫色事件。许多这些事件的顶部是红色的。这是一个警告信号。将鼠标悬停在这些事件上,您会看到DevTools警告您的页面可能是强制reflow(回流)的受害者。强制reflow(回流)只是强制同步布局的另一个名称。

6.png

现在是时候来看一下导致所有强制同步布局的函数了。点击其中一个布局事件,选择它。在Summary(摘要)窗格中,您现在应该可以看到有关此事件的详细信息。点击Layout Forced(布局强制)下的链接(update @ forcedsync.html:457)跳转到函数定义。

7.png

您现在应该在Sources(源文件)面板中看到函数的定义。

8.png

update()函数是requestAnimationCallback()的回调函数。该函数根据图片的offsetTop值计算每个图像的left属性。这将迫使浏览器立即执行新布局,以确保它提供正确的值。在每个动画帧期间强制布局是页面上的动画卡顿的原因。

所以现在你已经确定了问题,你可以尝试直接在DevTools中修复它。

在DevTools里修复问题

这个脚本内嵌在HTML中,因此您无法通过Sources(源文件)面板编辑它(*.js中的脚本可以在Sources(源文件)面板中编辑)。

但是,要测试您的更改,您可以在Console(控制台)中重新定义该函数。将函数定义从HTML文件复制并粘贴到DevTools Console(控制台)中。删除使用offsetTop的语句,并取消注被注释的那条语句。完成后按Enter键。

9.png

重新启动动画。 现在你可以目测到动画执行更加顺滑。

使用其他录制进行验证

在修改代码后,总是开启另一个录制是非常好的做法,确认动画是否真的更快了,性能更好了。

11.png

确实好多了。