mcpField
F
frames

frames

github.com/playful-design测试与质量1685 次安装1 周前更新
代码仓库

关于 frames

Frames 是用于评估网页交互流畅度的技能,通过限速录制、帧预算分析和修复前后追踪,帮助开发者定位性能原因并用数据验证改动。

主要功能

  1. 014× CPU 限速交互录制
  2. 02帧与响应时间预算检查
  3. 03长帧原因分析
  4. 04修复前后数据验证
  5. 05按严重程度整理报告

适用场景

  1. 01诊断动画期间的掉帧
  2. 02排查超过 200ms 的交互
  3. 03在相同条件下验证性能修复

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/playful-design/router --skill frames

安装后在 Claude Code 中输入/frames确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
observe.js
agents/
openai.yaml

详细介绍

帧

此技能用于衡量交互是否流畅。它会在限速 CPU 上录制交互,追踪每个卡顿帧的原因,并通过第二次录制验证修复效果。

追踪数据,而非感觉

预算是精确的。每一帧都必须在一个刷新间隔内完成;在 60Hz 下为 16.7ms,并且动画进行时,不得有任何帧超过 50ms。每次交互都必须在 200ms 内绘制出响应。没有数字支撑的“感觉很流畅”不算结论。

关于动效应采用哪些数值,请参阅 motion。逐帧拆解动效,请参阅 deconstruct。查看运行结果,请参阅 verify。

1. 明确交互

写明路由、操作步骤和关键时刻,例如“打开命令面板并输入三个字母”。通过浏览器的模拟调用将 CPU 限速 4×,模拟中端手机。在未限速的笔记本上进行追踪属于 frames-throttle-the-cpu。

2. 录制

通过浏览器的 evaluate 调用运行 observe.js。调用 window.__frames.start(),将交互执行三次,然后调用 window.__frames.stop()。如果某个长帧没有对应的脚本名称,也要录制完整的性能分析数据。没有录制就报告流畅度,属于 frames-trace-not-feel。

3. 检查预算

将录制结果与预算进行比较。动画进行时出现丢帧或长动画帧,属于 frames-hold-the-budget。交互的 duration 超过 200ms,属于 frames-answer-in-200ms。指出时间花在输入延迟、处理还是呈现上。

4. 找出原因

查看每个长帧中的脚本及其强制布局耗时,然后检查这些脚本指向的代码。

在大型子树上为布局属性制作动画,会导致每一帧都重新布局。对整页面板使用 top 或 width 动画,属于 frames-compositor-properties。改用 transform 和 opacity。

写入样式后读取布局,会迫使浏览器在帧中途重新布局。在设置 style.height 的循环中读取 offsetHeight,属于 frames-no-forced-layout。先读取所有值,再写入。

每帧都更新状态,会导致每帧都重新渲染组件树。在 requestAnimationFrame 循环或滚动处理程序中调用 setState,属于 frames-animate-outside-render。通过 motion value、CSS 变量或 ref 驱动该值。

每帧都重绘大型区域,成本可能高于动效带来的价值。对移动的全屏图层使用 backdrop-filter,属于 frames-small-paint。缩小重绘区域,或淡入淡出静态副本。

5. 追踪修复效果

使用相同的步骤和限速设置再次录制。并排报告两次录制结果。“现在应该更快了”属于 frames-before-and-after。完成后,清除 CPU 限速。

成对对照

每项检查都要成对对照:出错的代码行旁边要列出替代它的代码行。

规则错误做法替代做法
frames-throttle-the-cpu在未限速的笔记本上追踪在 4× CPU 限速下追踪
frames-trace-not-feel“抽屉感觉很流畅”“打开抽屉:0 帧丢失,最差间隔为 17ms,限速 4×”
frames-hold-the-budget抽屉打开时丢失 14 帧丢帧 0 次,没有动画帧超过 50ms
frames-answer-in-200ms按键后 340ms 才绘制,其中 280ms 用于处理90ms,并将筛选操作移出按键处理
frames-compositor-properties对整页侧边栏使用 animate={{ width: 320 }}固定宽度,使用 animate={{ x: 0 }}
frames-no-forced-layout在遍历行的循环中执行 el.style.height = el.scrollHeight + "px"先读取所有高度,再统一写入
frames-animate-outside-render每帧调用一次 setProgress(p)在 motion value 上调用 progress.set(p)
frames-small-paint对移动的全屏图层使用 backdrop-filter: blur(20px)在静态背景上应用模糊效果,让面板在其上方移动
frames-before-and-after“现在应该更快了”修复前丢失 14 帧,修复后丢帧 0 次;限速 4×,步骤相同

报告

严重性。 在限速条件下,交互耗时超过 200ms,或未提供录制记录却报告页面流畅,属于 HIGH。动画期间出现丢帧、大型子树上有动画布局属性、强制布局或每帧更新一次状态,属于 MEDIUM。未启用限速进行的跟踪也属于此类。大范围重绘但仍在预算范围内,或报告修复却未进行第二次录制,属于 LOW。

格式。 每个根本原因列出一条发现,并附上测量数值:

1. file:line - [rule-id] what is wrong (dropped, worst gap, duration)

然后提供 Rule | Count | Severity 汇总。只要仍有任何 HIGH,就标记为 Block;否则标记为 Approve。对于不支持长动画帧的浏览器,脚本归因标记为 Not verified。

评论

支持 Markdown