关于 optimize-web-animations
optimize-web-animations 是用于审查和改善网页动画性能及清理工作的技能。它强调实测页面、暂停屏幕外动画、恢复可见动效,并验证导航后的资源清理。
主要功能
- 01基于浏览器的动画性能分析
- 02暂停屏幕外 CSS 动画
- 03控制 Canvas 和 WebGL 动画循环
- 04清理计时器、监听器和资源
- 05跨路由与视口验证行为
适用场景
- 01查找视口外仍在运行的动画
- 02减少不必要的 Canvas 或 WebGL 工作
- 03审查导航过程中的资源泄漏
- 04检查移动端和长页面的动画行为
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mengto/ skills --skill optimize-web-animations安装后在 Claude Code 中输入/optimize-web-animations确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamldemo/expected-output.mdindex.htmlinput.mdPROMPT.mdreferences/browser-profiling.md详细介绍
优化 Web 动画
核心原则
编辑前先测量实际页面。目标不是移除动态效果,而是让屏幕外的工作停止、可见的动态效果正确恢复,并在路由切换或卸载时清理长期占用的资源。
如有可用的 Codex Browser,请使用它,尤其是用于 localhost 页面。除非用户明确要求,否则不要使用 Chrome。
工作流
-
检查仓库上下文。
- 阅读
AGENTS.md或本地说明。 - 尽早运行
git status --short。 - 查找页面组件、动画钩子、CSS 关键帧、
requestAnimationFrame、setInterval、setTimeout、canvas/WebGL/物理效果组件、媒体元素、GSAP 时间线/补间,以及现有的可见性工具。 - 检查副作用清理代码中是否涉及事件监听器、观察器、RAF 循环、间隔计时器、定时器、外部脚本、媒体流、WebGL 纹理/材质/几何体/渲染器,以及可能在卸载后完成的异步任务。
- 如果工作区有未提交的更改,从一开始就规划好如何精准暂存。
- 阅读
-
在浏览器中采集基线数据。
- 打开用户指定的确切路由。
- 在页面顶部、中部、页脚/下方内容处进行分析;如果布局可能不同,还要测试一个移动设备视口。
- 根据计算后的
animationName、animationPlayState和可见性统计 CSS 动画。包括::before和::after。 - 单独检查 canvas/WebGL 元素;CSS 分析无法证明 RAF 循环已停止。
- 记录屏幕外仍在运行的动画名称及负责这些动画的 DOM 节点。
- 对于内存/泄漏相关请求,还要记录元素/canvas/image/iframe 的数量、可获取的 JS 堆指标、空闲 10-30 秒后的采样结果,以及简短的路由循环采样。如果堆 API 返回
null,或 Browser 沙盒阻止了猴子补丁,请说明这一点,并依靠稳定的可观测数量和源码审查得出结论。 - 压力测试应保持在有限范围内。Browser 标签页在分析期间崩溃可以作为负载过高的证据,但除非通过最小化测试复现,否则不要过度归因。
- 可复用的 Codex Browser 求值器请参阅
references/browser-profiling.md。
-
修改控制动态效果的最小范围节点。
- 如果应用已有页面渐显/可见性钩子,优先使用。
- 否则添加一个
IntersectionObserver,在区块和带动画的子元素上切换is-offscreen等稳定类名。 - 使用有针对性的规则暂停 CSS 动画:
main > section.is-offscreen .expensive-animation,
.expensive-animation.is-offscreen {
animation-play-state: paused !important;
}
- 对于重复卡片或占位符,请观察卡片容器及其动画后代,而不是整个文档。
- 对于跑马灯/滚动字幕轨道,当其所在区域移出屏幕时暂停轨道。
- 对于骨架屏加载器和伪元素微光效果,在需要时添加
::before和::after暂停选择器。 - 对于 canvas/WebGL/物理模拟循环,直接控制 RAF 循环:
- 当 canvas/容器进入视口时启动。
- 移出视口时取消
requestAnimationFrame。 - 重新进入视口时恢复。
- 清理时断开观察器并取消帧。
- 如有助于浏览器验证,添加非视觉调试标记,例如
data-animation-active。
- 如果组件已支持
prefers-reduced-motion,请予以保留,并避免因滚动/动画状态引入 React 渲染循环。 - 为防止泄漏:
- 清除 effect 创建的所有 timeout/interval。
- 在卸载前及重启循环前取消 RAF。
- 断开
IntersectionObserver、ResizeObserver、MutationObserver和自定义订阅。 - 使用同一个处理函数引用移除全局/window/document 监听器。
- 释放 Three/WebGL 纹理、材质、几何体和渲染器,并移除渲染器 DOM 节点。
- 清除作用于 DOM 节点和可变对象(例如着色器 uniforms)的 GSAP 补间动画/时间线。
- 停止媒体流,并暂停已分离的视频/音频源。
- 使用
isDisposed标志保护异步加载器;若资源在卸载后才加载完成,则释放这些资源。 - 在 React 清理函数中,如果 lint 提示 ref 可能发生变化,请在 effect 内捕获
ref.current的值,然后再返回清理函数。 - 在因不可见而暂停后,限制物理或模拟帧的时间增量,避免延迟帧执行过大的更新。
-
验证实际行为,而不只是构建是否通过。
- 重新加载路由,并重新运行相同的顶部/中部/页脚/移动端配置。
- 目标结果:受测页面区域的
offscreenRunningCount: 0。 - 确认可见动画仍会运行,或在滚动进入视口时恢复。
- 确认 RAF/canvas 循环在视口外报告为非活动状态,在视口内报告为活动状态;或者通过源码/运行时状态证明循环已取消。
- 对于泄漏审计,对比路由循环前后的数据以及空闲时的采样结果。重复导航后,DOM/canvas/图像数量应恢复到相同基线,允许存在少量符合预期的异步内容变化。
- 执行常规页面交互,例如搜索/筛选/导航,以确保观察器不会破坏动态内容。
- 检查新开标签页中的控制台警告/错误。
-
运行本地检查。
- 使用仓库的常规检查流程。对于 React/Vite 应用,通常为:
git diff --check
npm run lint
npm run build
- 将已知的非致命警告与失败分别说明。
- 按仓库/用户说明的要求谨慎提交。
- 如果存在无关的未提交更改,请使用独立索引:
rm -f /tmp/<task>-index
GIT_INDEX_FILE=/tmp/<task>-index git read-tree HEAD
# Apply only the intended hunks to the temporary index.
GIT_INDEX_FILE=/tmp/<task>-index git diff --cached --check
GIT_INDEX_FILE=/tmp/<task>-index git commit -m "Pause offscreen <page> animations"
git restore --staged <files> 2>/dev/null || true
- 如果工作区有未提交更改,除非所有代码块都属于当前任务,否则不要暂存范围过大的文件。
- 提供有证据支撑的报告。
- 先说明发现:哪些内容仍在运行、哪些内容看起来容易泄漏,以及哪些内容无法测量。
- 将源码审计风险与浏览器实时测量结果分开说明。
- 列出准确的采样路由、视口外动画计数、DOM/canvas 数量稳定性、路由循环结果和本地检查结果。
- 明确说明限制,尤其是无法获取的堆计数器或受阻的浏览器检测功能。
良好的修复模式
- 对于较长的区块,使用区块级
is-offscreen和元素级is-offscreen,以防首屏下方子元素的动画仍在运行。 - 按路由定义共享的可见性选择器常量,例如
COURSES_PAGE_ANIMATION_VISIBILITY_SELECTOR。 - 使用约为
0.01的IntersectionObserver阈值来控制动画。 - 直接控制 WebGL/canvas 效果的 RAF 循环;CSS
animation-play-state无法暂停 JavaScript 渲染循环。 - 为在暂停或延迟帧后恢复的物理循环限制帧间隔。
- 为 GSAP/WebGL 效果中使用的 React ref 捕获清理节点。
- 为可能在卸载后才完成的图像/视频/纹理/数据加载器添加
isDisposed防护。 - 进行简短的空闲和路由循环探测,以发现不断累积的 DOM 节点、画布、iframe 或未释放的媒体。
避免
- 为了通过性能配置检查而移除所有动画。
- 因祖先选择器过于宽泛而暂停可见的首屏动效。
- 认为
animation-play-state也能控制伪元素或 JavaScript RAF 循环。 - 仅凭页面顶部的一次测量来判断长页面的情况。
- 将不可用的堆计数器视为没有内存泄漏的证据。
- 在 Browser 中运行无界压力循环;应使用有界循环,并记录崩溃情况,但不要夸大其因果关系。
- 仅凭截图作为性能证明。
- 将无关的本地代码改动一并提交。
评论
支持 Markdown