mcpField
O
optimize-web-animations

optimize-web-animations

github.com/mengto開発7.1k1.7k 回インストール3 日前に更新
リポジトリ

optimize-web-animations について

optimize-web-animationsは、Webアニメーションの性能とクリーンアップを調査・改善するスキルです。実ページを計測し、画面外の処理を停止して表示中に再開し、遷移後のリソース解放を検証します。

主な機能

  1. 01ブラウザーでのアニメーション計測
  2. 02画面外のCSSアニメーション停止
  3. 03Canvas・WebGLループの制御
  4. 04タイマー・リスナー・リソースの解放
  5. 05ルートや表示領域をまたぐ動作検証

活用シーン

  1. 01画面外で動き続けるアニメーションの特定
  2. 02不要なCanvas・WebGL処理の削減
  3. 03画面遷移時のリソースリーク監査
  4. 04モバイルや長いページでの動作確認

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/optimize-web-animationsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
demo/
expected-output.md
index.html
input.md
PROMPT.md
references/
browser-profiling.md

詳細

Web アニメーションを最適化する

基本ルール

編集する前に、実際のページを計測します。目的は動きをなくすことではなく、画面外の処理を停止し、表示中の動きを正しく再開させ、ルート変更やアンマウント時に長期間保持されるリソースを解放することです。

利用可能な場合は、特に localhost のページで Codex Browser を使用してください。ユーザーから明示的に依頼された場合を除き、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 evaluator については、references/browser-profiling.md を参照してください。
  3. 動きを制御する最小範囲の所有者にパッチを適用します。

    • アプリに既存のページ表示/可視性フックがある場合は、そちらを優先します。
    • ない場合は、セクションやアニメーションする子要素に is-offscreen などの安定したクラスを切り替える IntersectionObserver を追加します。
    • 対象を絞ったルールで 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 のレンダーループを導入しないでください。
  • リーク対策を強化します。
    • エフェクトで作成したタイムアウト/インターバルをすべてクリアします。
    • アンマウント前とループ再開前に RAF をキャンセルします。
    • IntersectionObserver、ResizeObserver、MutationObserver、カスタムサブスクリプションを切断します。
    • 同じハンドラー参照を使って、グローバル/window/document のリスナーを削除します。
    • Three/WebGL のテクスチャ、マテリアル、ジオメトリ、レンダラーを破棄し、レンダラーの DOM ノードを削除します。
    • DOM ノードやシェーダーのユニフォームなどの可変オブジェクトに対する GSAP のトゥイーン/タイムラインを停止します。
    • メディアストリームを停止し、切り離された動画/音声ソースを一時停止します。
    • 非同期ローダーを isDisposed フラグで保護し、アンマウント後に読み込みが完了した場合は、読み込まれたリソースを破棄します。
    • React のクリーンアップで、ref が変更される可能性があるという lint の警告が出た場合は、クリーンアップを返す前にエフェクト内で 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 を設定します。これにより、画面外にある子要素のアニメーションも実行されないようにできます。
  • ルートごとに、COURSES_PAGE_ANIMATION_VISIBILITY_SELECTOR のような共通の表示判定セレクター定数を用意します。
  • アニメーションを制御する IntersectionObserver のしきい値は、0.01 前後にします。
  • WebGL/canvas のエフェクトでは、RAF ループを直接制御します。CSS の animation-play-state では JavaScript のレンダーループを一時停止できません。
  • 一時停止後、またはフレームが遅延した後に再開する物理演算ループには、フレームデルタの上限を設定します。
  • GSAP/WebGL エフェクトで使う React の ref については、クリーンアップ対象のノードを取得して保持します。
  • アンマウント後に解決する可能性がある画像/動画/テクスチャ/データのローダーには、isDisposed によるガードを設定します。
  • 短時間のアイドル状態とルート切り替えを調べ、DOM ノード、canvas、iframe の蓄積やメディアの解放漏れを検出します。

避けること

  • プロファイルの合格を目的に、すべてのアニメーションを削除すること。
  • 祖先要素のセレクターが広すぎるために、表示中のヒーローアニメーションまで一時停止すること。
  • animation-play-state が疑似要素や JavaScript の RAF ループにも適用されると思い込むこと。
  • 長いページを、ページ最上部での測定だけで判断すること。
  • 利用できないヒープカウンターを、メモリリークがない証拠として扱うこと。
  • Browser で上限のないストレステストを実行すること。回数を制限し、クラッシュを記録しつつ、因果関係を誇張しないでください。
  • スクリーンショットだけをパフォーマンスの証拠にすること。
  • 無関係なローカル変更をコミットに含めること。

コメント