00:00:00GitHub 最近为 Storybook 发布了一个非常强大的插件,彻底改变了
00:00:05我们测试组件性能的方式。
00:00:07它包含一个非常详细的性能面板,提供了许多有价值的见解,例如测量
00:00:12帧耗时、输入响应速度、布局稳定性、React 分析、内存压力
00:00:18以及更多内容。
00:00:19在这段视频中,我们将深入了解这个插件提供的功能。
00:00:23这会非常有趣,让我们开始吧。
00:00:31在开始之前,先问个简单的问题。
00:00:32你知道什么是“性能测试左移”吗?
00:00:35这是一种开发范式,它规定应用组件的性能
00:00:40应该在开发过程的早期进行测试,而不是事后才考虑。
00:00:45而这个工具正是为了帮助开发者做出这些早期判断而构建的,
00:00:50让你在组件进入生产环境之前,实时查看它们的表现。
00:00:55因此,Storybook 性能面板提供了关于组件
00:01:00如何与浏览器渲染引擎交互的高保真视图。
00:01:02例如,它会追踪帧耗时来识别抖动,也就是那些
00:01:07导致动画感觉卡顿的微小不规则帧间隔。
00:01:10它还会监控主线程的 DOM 剧变和布局抖动。
00:01:15DOM 剧变发生在代码在紧密循环中不必要地创建、删除或更新元素时,
00:01:20而布局抖动则是因为你在连续读写样式,
00:01:25导致浏览器在单帧内被迫多次重新计算布局。
00:01:30而且这个插件可以适配你使用的任何框架。
00:01:33如果你使用 React,它可以突出显示渲染级联等指标,
00:01:38即那些由于细微状态变化,意外触发了整个应用的大规模缓慢重渲染。
00:01:44它还会追踪 P95 耗时,这能显示最慢用户面临的最坏情况,
00:01:50而不仅仅是平均值。
00:01:52如果你没用 React,它的通用模式也完美支持 Vue、Svelte 或 Web Components。
00:01:59为了获得最佳效果,建议在 Chrome 或 Edge 上运行此插件。
00:02:04他们还有一个实时演示文档,我们可以在其中看到这些指标的实际应用。
00:02:08例如,在动画方块示例中,我们可以精确追踪
00:02:13动画期间发生了多少次内联样式变更。
00:02:16在这种情况下,一切看起来都很健康。
00:02:18帧率和帧耗时保持完美稳定,这意味着浏览器
00:02:23毫不费力地处理了这些样式更新。
00:02:25然而,“重型列表”示例则呈现了不同的情况。
00:02:29当我们过滤这个大列表时,会看到一些警告信号。
00:02:32首先,累积布局偏移(CLS)跳到了一个很高的值,这表明
00:02:38元素在加载时发生了剧烈跳动,给用户带来了糟糕的体验。
00:02:43我们还看到了 DOM 剧变的峰值,这意味着浏览器
00:02:49正在超负荷工作,以便同时销毁并重建大量节点。
00:02:52这也会导致掉帧,从而破坏了界面的
00:02:57感知速度和流畅度。
00:02:58在元素计时示例中,任何带有 element timing 属性的 DOM 元素
00:03:04都会被测量其确切的渲染时间。
00:03:06这非常有用,因为它可以帮助你识别核心内容
00:03:11或行动号召按钮变得可见的精确时刻,从而提供更准确的
00:03:17感知性能图景,而不仅仅是通用的页面加载指标。
00:03:21看看“昂贵渲染”示例,如果我们点击重渲染按钮,
00:03:26会导致 P95 耗时飙升。
00:03:29这是因为主线程被繁重的 JavaScript 执行所占据,
00:03:34使 UI 感觉非常迟钝。
00:03:36我们在这里还看到了帧抖动警告,这表明渲染不一致,
00:03:41帧与帧之间的时间间隔波动剧烈。
00:03:44此外还有很高的总阻塞时间(TBT)。
00:03:47TBT 是一个主要的警告信号,因为它表明主线程被阻塞了
00:03:52足够长的时间,以至于阻止了用户与页面进行交互,
00:03:57比如点击按钮或滚动。
00:03:58我们在“记忆化浪费”示例中也看到了类似的分解。
00:04:03这里的演示显示,不必要地重渲染每个元素
00:04:08会导致严重的延迟。
00:04:09相比之下,经过正确记忆化处理(memoized)的示例显示了
00:04:15如果我们对组件进行记忆化,可以节省多少工作量。
00:04:16通过跳过那些冗余的渲染,我们保持了主线程的清空和帧率的稳定,
00:04:21从而获得了极其流畅的 60 FPS 体验。
00:04:25在渲染级联示例中,我们看到了在
00:04:30useLayoutEffect 内部使用 setState 会发生什么。
00:04:31每一次增量都会触发级联,因为 useLayoutEffect 在
00:04:37所有 DOM 变更之后、但在浏览器绘制之前同步运行。
00:04:42因此,通过在这里触发状态更新,你是在迫使 React 重新处理组件树,
00:04:47并让浏览器在用户看到第一个结果之前,
00:04:52第二次重新计算布局。
00:04:53这很糟糕,因为它实际上使每一帧的工作量翻倍,
00:04:58导致的渲染延迟即使是简单的交互也会感觉沉重。
00:05:02还有“样式剧变”示例,它也展示了一个关键的观察结果。
00:05:07当我们同时更改 600 个不同节点的内联样式时会发生什么?
00:05:13我们立即在抖动部分看到了这些停顿警告,这表明
00:05:18浏览器被迫进入了重排(reflow)循环。
00:05:21它试图在 JavaScript 仍在进行更改的同时,
00:05:26计算 600 个元素的位置。
00:05:27这导致帧指标的生命体征非常不健康,
00:05:33因为主线程已经完全饱和。
00:05:34所以我希望所有这些例子都能向你展示如何使用这个 Storybook 插件,
00:05:38在更精确的环境中识别瓶颈。
00:05:41当然,你可以使用像 Lighthouse 这样的工具,但 Lighthouse 只是个“粗刷子”。
00:05:46它无法提供那种外科手术般的精度,无法看到单个组件
00:05:51具体是如何影响应用性能的。
00:05:53我非常鼓励大家下载这个插件,把它添加到你的 Storybook 工具套件中并试用一下。
00:05:59一旦你看到了组件在底层运行的全貌,
00:06:03你将会获得非常多有价值的见解。
00:06:06这就是全新的 GitHub Storybook 性能面板插件的简要介绍。
00:06:11你觉得它怎么样?
00:06:13你又是如何在你的应用中测量性能的呢?
00:06:16请在下方的评论区告诉我们。
00:06:18朋友们,如果你喜欢这类技术解析,请点击
00:06:22视频下方的点赞按钮,也别忘了订阅我们的频道。
00:06:28我是来自 Better Stack 的 Andres,我们下个视频再见。