mcpField
O
optimize-web-animations

optimize-web-animations

github.com/akillness开发5359 次安装今天更新
代码仓库

关于 optimize-web-animations

面向前端项目的编码技能,用于诊断和改善动画性能。它通过浏览器测量暂停屏幕外的动画,同时保留可见动画并清理长期运行的资源。

主要功能

  1. 01修改前后测量动画状态
  2. 02暂停屏幕外的 CSS 动画
  3. 03控制 Canvas 和 WebGL 动画循环
  4. 04清理计时器、监听器和图形资源
  5. 05验证可见状态与路由循环稳定性

适用场景

  1. 01减少屏幕外动画的 CPU 和 GPU 开销
  2. 02排查动画导致的滚动卡顿
  3. 03审查 RAF 循环和资源泄漏

安装

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

$npx skills add https://github.com/akillness/jeo-skills --skill optimize-web-animations

安装后在 Claude Code 中输入/optimize-web-animations确认已加载。

包含的文件

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

SKILL.toon
agents/
openai.yaml
references/
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。

工作流

  1. 检查仓库上下文。

    • 阅读 AGENTS.md 或本地说明。
    • 尽早运行 git status --short。
    • 查找页面组件、动画钩子、CSS 关键帧、requestAnimationFrame、setInterval、setTimeout、canvas/WebGL/物理效果组件、媒体元素、GSAP 时间线/补间动画,以及现有的可见性工具。
    • 检查副作用清理逻辑,确认其处理了事件监听器、观察器、RAF 循环、间隔、计时器、外部脚本、媒体流、WebGL 纹理/材质/几何体/渲染器,以及卸载后仍可能完成的异步工作。
    • 如果工作区有未提交更改,请从一开始就规划好如何精准暂存。
  2. 在浏览器中采集基线。

    • 打开用户指定的确切路由。
    • 在页面顶部、中部、页脚/下方内容,以及一种移动端视口下进行性能分析(布局可能不同时)。
    • 根据计算后的 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。
  3. 修改控制动效的最小范围组件。

    • 如果应用已有页面显现/可见性钩子,优先使用。
    • 否则,添加 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 的值,然后再返回清理函数。
    • 在因不可见而暂停后,限制物理或模拟帧的时间增量,避免延迟帧执行过大的更新。
  1. 验证实际行为,而不只是构建是否通过。

    • 重新加载路由,并重新运行相同的顶部/中部/页脚/移动端配置。
    • 目标结果:受测页面区域的 offscreenRunningCount: 0。
    • 确认可见动画仍会运行,或在滚动进入视口时恢复。
    • 确认 RAF/canvas 循环在视口外报告为非活动状态,在视口内报告为活动状态;或者通过源码/运行时状态证明循环已取消。
    • 对于泄漏审计,对比路由循环前后的数据以及空闲时的采样结果。重复导航后,DOM/canvas/图像数量应恢复到相同基线,允许存在少量符合预期的异步内容变化。
    • 执行常规页面交互,例如搜索/筛选/导航,以确保观察器不会破坏动态内容。
    • 检查新开标签页中的控制台警告/错误。
  2. 运行本地检查。

    • 使用仓库的常规检查流程。对于 React/Vite 应用,通常为:
git diff --check
npm run lint
npm run build
  • 将已知的非致命警告与失败分别说明。
  1. 按仓库/用户说明的要求谨慎提交。
    • 如果存在无关的未提交更改,请使用独立索引:
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
  • 如果工作区有未提交更改,除非所有代码块都属于当前任务,否则不要暂存范围过大的文件。
  1. 提供有证据支撑的报告。
    • 先说明发现:哪些内容仍在运行、哪些内容看起来容易泄漏,以及哪些内容无法测量。
    • 将源码审计风险与浏览器实时测量结果分开说明。
    • 列出准确的采样路由、视口外动画计数、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 中运行无界压力循环;使用有界循环,并记录崩溃情况,但不要夸大其因果关系。
  • 仅凭截图证明性能。
  • 让无关的本地代码改动混入提交。

参考资料

评论

支持 Markdown