关于 optimize-web-animations
面向前端项目的编码技能,用于诊断和改善动画性能。它通过浏览器测量暂停屏幕外的动画,同时保留可见动画并清理长期运行的资源。
主要功能
- 01修改前后测量动画状态
- 02暂停屏幕外的 CSS 动画
- 03控制 Canvas 和 WebGL 动画循环
- 04清理计时器、监听器和图形资源
- 05验证可见状态与路由循环稳定性
适用场景
- 01减少屏幕外动画的 CPU 和 GPU 开销
- 02排查动画导致的滚动卡顿
- 03审查 RAF 循环和资源泄漏
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ akillness/ jeo-skills --skill optimize-web-animations安装后在 Claude Code 中输入/optimize-web-animations确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
SKILL.toonagents/openai.yamlreferences/browser-profiling.md详细介绍
优化 Web 动画
何时使用此技能
- 用户要求提升动画性能、暂停屏幕外动画,或在 React/Vite/Next/前端页面上重复进行“仅在视口内播放”优化。
- 用户报告内存泄漏、页面长时间运行后导致电脑变慢,或希望审查并释放长生命周期资源(RAF 循环、监听器、观察器、计时器、GSAP 补间动画、WebGL 对象)。
- 用户希望修复滚动卡顿,或降低 CSS 动画、canvas/WebGL
requestAnimationFrame循环、跑马灯/信息滚动条、骨架屏加载器或 GSAP/Three/Matter 效果的 CPU/GPU 占用。 - 工作需要在浏览器中执行“先测量基线,再修复”的循环(优先使用 Codex Browser),通过
IntersectionObserver/is-offscreen类控制动画,并通过offscreenRunningCount、DOM/canvas 数量和路由循环稳定性进行验证,而非仅凭截图判断。 - 修复需要遵循源码级清理规范:清除计时器、取消 RAF、断开观察器、移除监听器,并在卸载时释放 Three/WebGL/GSAP 资源。
- 不适用于一般性能问题排查(判断性能跟踪、查询计划、负载测试结果或 CWV/Lighthouse 报告的含义,或决定应优先优化延迟/吞吐量/内存/包体积中的哪个瓶颈)——请改用
performance-optimization;只有在已确认目标是与动画/动效相关的前端工作时,才使用此技能。
核心规则
编辑前先测量真实页面。目标不是移除动效,而是让屏幕外的工作停止、可见动效正确恢复,并在路由切换/组件卸载时释放长生命周期资源。
如果可用,请使用 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/图片/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/画布效果的 RAF 循环;
animation-play-state无法暂停 JavaScript 渲染循环。 - 对暂停或延迟帧后恢复的物理循环限制帧间隔。
- 为 GSAP/WebGL 效果使用的 React refs 捕获清理节点。
- 对卸载后仍可能完成的图像/视频/纹理/数据加载器使用
isDisposed保护。 - 进行简短的空闲和路由循环探测,以发现不断累积的 DOM 节点、画布、iframe 或未释放的媒体。
避免
- 为了让性能评估通过而移除所有动画。
- 因祖先选择器范围过广而暂停可见的主视觉区域动效。
- 认为
animation-play-state能覆盖伪元素或 JavaScript RAF 循环。 - 只相信长页面顶部的一次测量结果。
- 将无法获取堆计数器视为没有内存泄漏的证明。
- 在 Browser 中运行无界压力循环;使用有界循环,并记录崩溃情况,但不要夸大其因果关系。
- 仅凭截图证明性能。
- 让无关的本地代码改动混入提交。
参考资料
- 上游源码:https://github.com/MengTo/Skills/tree/main/agent-skills/codex/optimize-web-animations
- references/browser-profiling.md — 用于屏幕外元素/动画性能分析的可复用 Codex Browser 评估器
- agents/openai.yaml — 随附的 Agent 配置
评论
支持 Markdown