mcpField
F
frames

frames

github.com/raphaelsalaja其他469 次安装今天更新
代码仓库

关于 frames

Frames 是用于测量运行中网页响应速度和动画性能的技能。它在 CPU 降速时记录交互、追踪慢帧对应的代码,并用相同方式再次录制来验证修复。

主要功能

  1. 01以 4× CPU 降速录制交互
  2. 02测量帧率与响应时间预算
  3. 03追踪慢帧和强制布局
  4. 04识别高开销动画模式
  5. 05对比修复前后的录制结果

适用场景

  1. 01测量 CPU 降速时的页面交互
  2. 02查找动画丢帧的原因
  3. 03调查用户输入响应缓慢的问题
  4. 04通过重复追踪验证性能修复

安装

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

$npx skills add https://github.com/raphaelsalaja/skills --skill frames

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

附带文件agents/openai.yamlobserve.js

README 原文English

来自项目 README

README 暂无中文译文,以下为英文原文;中文介绍见上方。

Frames

This skill measures whether an interaction stays smooth. It records the interaction on a throttled CPU, traces each slow frame to its cause and proves the fix with a second recording.

A trace, never a feeling

The budgets are exact. Every frame lands within one refresh interval, 16.7ms at 60Hz, and no animation frame runs past 50ms while something moves. Every interaction paints its response within 200ms. "Feels smooth" with no numbers is a finding.

What a motion's values should be belongs to motion. Taking a motion apart frame by frame belongs to deconstruct. Opening the running result belongs to verify.

1. Name the interaction

Write the route, the steps and the moment that matters, such as "open the command palette and type three letters". Throttle the CPU 4× through the browser's emulation call, which stands in for a mid-range phone. A trace on an unthrottled laptop is frames-throttle-the-cpu.

2. Record it

Run observe.js through the browser's evaluate call. Call window.__frames.start(), perform the interaction three times, then call window.__frames.stop(). When a long frame has no named script, record a full performance profile too. Reporting smoothness without a recording is frames-trace-not-feel.

3. Read the budget

Compare the recording against the budgets. Dropped frames or a long animation frame while something moves is frames-hold-the-budget. An interaction whose duration passes 200ms is frames-answer-in-200ms. Name whether the time went to input delay, processing or presentation.

4. Find the cause

Read each long frame's scripts and their forced layout time, then the code they point to.

A layout property animated across a large subtree reflows every frame. top or width animated on a full-page panel is frames-compositor-properties. Move it to transform and opacity.

Reading layout after writing a style forces the browser to lay out mid-frame. offsetHeight read inside a loop that sets style.height is frames-no-forced-layout. Read every value first, then write.

A state update on every frame re-renders the component tree each frame. setState inside a requestAnimationFrame loop or a scroll handler is frames-animate-outside-render. Drive the value through a motion value, a CSS variable or a ref.

A large surface repainted each frame costs more than the motion is worth. backdrop-filter on a full-screen layer that moves is frames-small-paint. Shrink the painted area or fade a static copy.

5. Trace the fix

Record again with the same steps and the same throttle. Report both recordings side by side. "Should be faster now" is frames-before-and-after. Clear the CPU throttle when done.

The pair

Every check is a pair. The broken line sits beside the line that replaces it.

RuleBrokenReplacement
frames-throttle-the-cpuTraced on an unthrottled laptopTraced at 4× CPU throttle
frames-trace-not-feel"The drawer feels smooth""Drawer open: 0 dropped frames, worst gap 17ms at 4×"
frames-hold-the-budget14 dropped frames while the sheet opens0 dropped, no animation frame over 50ms
frames-answer-in-200msA keystroke painting after 340ms, 280ms of it processing90ms, with the filter moved off the keystroke
frames-compositor-propertiesanimate={{ width: 320 }} on the full-page sidebaranimate={{ x: 0 }} with the width fixed
frames-no-forced-layoutel.style.height = el.scrollHeight + "px" in a loop over rowsAll heights read first, then all written
frames-animate-outside-rendersetProgress(p) on every frameprogress.set(p) on a motion value
frames-small-paintbackdrop-filter: blur(20px) on a moving full-screen layerBlur on the static backdrop, the panel moving above it
frames-before-and-after"Should be faster now"Before 14 dropped, after 0, same steps at 4×

Reporting

Severity. HIGH is an interaction over 200ms at the throttle, or a report of smoothness with no recording. MEDIUM is dropped frames during motion, a layout property animated on a large subtree, forced layout or a state update per frame. It is also a trace taken without a throttle. LOW is a large repaint that still holds the budget, or a fix reported without a second recording.

Format. One finding per root cause, with the measured numbers:

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

Then a Rule | Count | Severity summary. Block when any HIGH remains, Approve otherwise. Mark a browser without long animation frame support as Not verified for script attribution.

评论

支持 Markdown