诊断强制同步布局(Layout)
了解如何使用DevTools诊断强制同步布局。
在本指南中,您通过一个demo来识别和解决问题,了解如何调试强制同步布局。 演示动画图像使用requestAnimationFrame(), 这是基于帧的动画的推荐方法。 然而,在动画中有相当多的卡顿。你的目标是确定卡顿的原因并解决这个问题,让demo中的动画能够达到顺滑的60 FPS。
收集数据
首先,您需要收集数据,以便您可以准确了解页面运行时会发生什么。
- 打开演示页面。
- 打开DevTools的
Timeline
(时间轴)面板。 - 启用
JS Profile
(JS分析)文件选项。当后面分析火焰图时,此选项将让您准确查看调用的函数。 - 点击页面上的
Start
(开始)按钮以启动动画。 - 点击
Timeline
(时间轴)面板上的Record
(录制)按钮以开始时间轴录制。 - 等待几秒钟。
- 再次点击
Record
(录制)按钮,停止录制。
录制完成后,您应该在Timeline
(时间轴)面板上看到类似下面的内容。
识别问题
现在你有你的数据,是时候开始理解它了。
乍看上去,您可以在Timeline
(时间轴)录制的Summary
(摘要)窗格中看到浏览器在rendering
(渲染)上花了大部分时间。一般来说,如果您可以优化页面的layout
(布局)操作,就可以减少rendering
(渲染)花费的时间。
现在将注意力移到Overview
(概览)窗格正下方的粉红色时间条。时间条代表帧。将鼠标悬停在他的上面,可以查看有关该帧的更多信息。
这些帧需要很长时间才能完成。为了平滑的动画,帧频率需要达到60 FPS。
现在是时候诊断究竟是哪里有问题。使用鼠标,放大调用栈。
栈的顶部是Animation Frame Fired
(动画帧触发)事件。只要触发此事件,就会调用传递给requestAnimationFrame()
的函数。在Animation Frame Fired
(动画帧触发)你看到Function Call
(函数调用),和下面你看到update
。你可以推断一个名为update()
的方法是requestAnimationFrame()
的回调。
JS Profile
(JS分析)选项有用的地方。如果它被禁用,你只会看到`Function Call`(函数调用),然后是所有小的紫色事件(下面讨论),没有关于确切地调用哪些函数的详细信息(注:看不到具体是哪个函数被调用了)。现在,将注意力集中在update
事件下面的所有小的紫色事件。许多这些事件的顶部是红色的。这是一个警告信号。将鼠标悬停在这些事件上,您会看到DevTools警告您的页面可能是强制reflow
(回流)的受害者。强制reflow
(回流)只是强制同步布局的另一个名称。
现在是时候来看一下导致所有强制同步布局的函数了。点击其中一个布局事件,选择它。在Summary
(摘要)窗格中,您现在应该可以看到有关此事件的详细信息。点击Layout Forced
(布局强制)下的链接(update @ forcedsync.html:457
)跳转到函数定义。
您现在应该在Sources
(源文件)面板中看到函数的定义。
update()
函数是requestAnimationCallback()
的回调函数。该函数根据图片的offsetTop
值计算每个图像的left
属性。这将迫使浏览器立即执行新布局,以确保它提供正确的值。在每个动画帧期间强制布局是页面上的动画卡顿的原因。
所以现在你已经确定了问题,你可以尝试直接在DevTools中修复它。
在DevTools里修复问题
这个脚本内嵌在HTML中,因此您无法通过Sources
(源文件)面板编辑它(*.js
中的脚本可以在Sources
(源文件)面板中编辑)。
但是,要测试您的更改,您可以在Console
(控制台)中重新定义该函数。将函数定义从HTML文件复制并粘贴到DevTools Console
(控制台)中。删除使用offsetTop
的语句,并取消注被注释的那条语句。完成后按Enter键。
重新启动动画。 现在你可以目测到动画执行更加顺滑。
使用其他录制进行验证
在修改代码后,总是开启另一个录制是非常好的做法,确认动画是否真的更快了,性能更好了。
确实好多了。