mcpField
E
elite-performance

elite-performance

github.com/rshvr开发140 次安装10 周前更新
代码仓库

关于 elite-performance

面向 Web 开发者的性能优化 Skill,聚焦动画流畅度与 Core Web Vitals。内容涵盖动画实现、资源加载、内存清理和性能排查。

主要功能

  1. 01Core Web Vitals 与动画目标
  2. 02适合 GPU 加速的动画属性
  3. 03GSAP 清理与批处理
  4. 04加载策略与资源优化
  5. 05性能调试检查清单

适用场景

  1. 01检查动画代码中的布局触发属性
  2. 02规划动画库的加载方式
  3. 03排查掉帧或内存泄漏

安装

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

$npx skills add https://github.com/rshvr/elite-web-design --skill elite-performance

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

包含的文件

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

references/
animation-performance.md
asset-optimization.md
debugging.md
vite-setup.md

详细介绍

极致性能

在达到 Core Web Vitals 目标的同时,保持动画流畅运行在 60fps。

快速参考

主题参考文件
Vite 配置vite-setup.md
动画性能animation-performance.md
资源优化asset-optimization.md
调试debugging.md

性能预算(2026)

Core Web Vitals 目标
指标良好需改进较差
LCP(最大内容绘制)≤ 2.5s≤ 4.0s> 4.0s
INP(交互到下一次绘制)≤ 200ms≤ 500ms> 500ms
CLS(累积布局偏移)≤ 0.1≤ 0.25> 0.25
动画目标
指标目标
帧率60fps(16.67ms/帧)
帧预算JS/布局 < 10ms
动画启动响应时间 < 100ms
滚动卡顿丢帧数为 0
Bundle 目标
资源目标
初始 JS< 100KB(gzip 压缩后)
初始 CSS< 50KB(gzip 压缩后)
GSAP 核心约 25KB(gzip 压缩后)
初始资源总计< 200KB(gzip 压缩后)

GPU 加速属性

仅为这些属性添加动画
/* GPU composited - FAST */
transform: translateX() translateY() translateZ() scale() rotate() skew();
opacity: 0 to 1;
filter: blur() brightness() contrast();

/* Will trigger compositor layer */
will-change: transform, opacity;
绝不要为这些属性添加动画
/* Triggers layout - SLOW */
width, height
top, right, bottom, left
margin, padding
font-size
border-width

/* Triggers paint - SLOW */
background-color, color
border-color
box-shadow
text-shadow
transform 与 position
/* BAD - Triggers layout every frame */
.element {
  animation: moveLeft 1s;
}
@keyframes moveLeft {
  to {
    left: 100px;
  }
}

/* GOOD - GPU composited */
.element {
  animation: moveLeft 1s;
}
@keyframes moveLeft {
  to {
    transform: translateX(100px);
  }
}

快速提升性能的方法

1. 延迟加载首屏以下的内容

<img src="hero.jpg" alt="Hero" loading="eager" />
<img src="feature.jpg" alt="Feature" loading="lazy" />


<div class="lazy-section" data-component="heavy-animation">
  
</div>
2. 使用 content-visibility
/* Skip rendering off-screen sections */
.section {
  content-visibility: auto;
  contain-intrinsic-size: 0 500px; /* Estimated height */
}
3. 限制开销大的效果
/* Isolate animated sections */
.animated-section {
  contain: layout style paint;
}

/* Full containment for cards */
.card {
  contain: strict;
}
4. 在适当情况下减少动画
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
5. 优化滚动处理程序
// BAD - Fires on every scroll event
window.addEventListener("scroll", handleScroll);

// GOOD - Passive listener, no preventDefault
window.addEventListener("scroll", handleScroll, { passive: true });

// BETTER - Use ScrollTrigger (already optimized)
gsap.to(".element", {
  scrollTrigger: {/* ... */},
});

GSAP 性能

使用 gsap.context() 清理资源
// Prevents memory leaks
const ctx = gsap.context(() => {
  gsap.to(".element", { x: 100 });
  ScrollTrigger.create({/* ... */});
});

// On unmount
ctx.revert();
批量更新 ScrollTrigger
// Process multiple items efficiently
ScrollTrigger.batch(".item", {
  onEnter: (batch) =>
    gsap.to(batch, {
      opacity: 1,
      y: 0,
      stagger: 0.1,
    }),
});
使用 refreshPriority
// Control refresh order
ScrollTrigger.create({
  trigger: ".section",
  refreshPriority: -1, // Refresh after others
});
延迟创建 ScrollTrigger
// Don't create all at once
const createTrigger = (element) => {
  ScrollTrigger.create({
    trigger: element,
    start: "top 80%",
    onEnter: () => {
      // Create animation only when needed
      gsap.from(element, { opacity: 0, y: 50 });
    },
    once: true,
  });
};

// Create triggers as needed
gsap.utils.toArray(".section").forEach(createTrigger);

CSS 动画性能

高效的关键帧
/* GOOD - Only compositor properties */
@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* BAD - Triggers layout */
@keyframes slideIn {
  from {
    opacity: 0;
    margin-top: 30px;
  }
  to {
    opacity: 1;
    margin-top: 0;
  }
}
will-change 最佳实践
/* Apply just before animation */
.card {
  transition:
    transform 0.3s,
    opacity 0.3s;
}

.card:hover {
  will-change: transform;
}

/* Remove after animation */
.card.animating {
  will-change: transform, opacity;
}

/* Never do this globally */
/* * { will-change: transform; } NEVER! */
合成图层
/* Force new layer when needed */
.animated-element {
  transform: translateZ(0); /* or translate3d(0,0,0) */
}

/* Better: Use will-change temporarily */
.animating {
  will-change: transform;
}

加载策略

关键路径
<head>
  
  <style>
    /* Above-fold styles */
  </style>

  
  <link rel="preload" href="hero.webp" as="image" />
  <link rel="preload" href="font.woff2" as="font" crossorigin />

  
  <link
    rel="stylesheet"
    href="full.css"
    media="print"
    onload="this.media='all'"
  />
</head>

<body>
  

  
  <script src="gsap.min.js" defer></script>
  <script src="app.js" defer></script>
</body>
动态导入
// Load GSAP plugins only when needed
const loadScrollTrigger = async () => {
  const { ScrollTrigger } = await import("gsap/ScrollTrigger");
  gsap.registerPlugin(ScrollTrigger);
  return ScrollTrigger;
};

// Load on interaction or visibility
const section = document.querySelector(".scroll-section");
const observer = new IntersectionObserver(async ([entry]) => {
  if (entry.isIntersecting) {
    await loadScrollTrigger();
    initScrollAnimations();
    observer.disconnect();
  }
});
observer.observe(section);
渐进增强
// Check for animation support
const supportsAnimation = "animate" in document.documentElement;
const prefersReducedMotion = window.matchMedia(
  "(prefers-reduced-motion: reduce)",
).matches;

if (supportsAnimation && !prefersReducedMotion) {
  // Load animation library
  import("./animations.js");
} else {
  // Show final states immediately
  document.querySelectorAll(".animated").forEach((el) => {
    el.classList.add("animation-complete");
  });
}

内存管理

清理动画
// Store references for cleanup
const animations = [];
const scrollTriggers = [];

function initAnimations() {
  animations.push(gsap.to(".element", { x: 100 }));

  scrollTriggers.push(ScrollTrigger.create({ trigger: ".section" }));
}

function cleanup() {
  animations.forEach((anim) => anim.kill());
  scrollTriggers.forEach((st) => st.kill());
  animations.length = 0;
  scrollTriggers.length = 0;
}

// Or use gsap.context()
const ctx = gsap.context(() => {
  // All animations here
});

// Cleanup
ctx.revert();
SplitText 清理
const splits = [];

function initTextAnimations() {
  document.querySelectorAll(".split-text").forEach((el) => {
    const split = new SplitText(el, { type: "chars" });
    splits.push(split);

    gsap.from(split.chars, {
      opacity: 0,
      y: 20,
      stagger: 0.02,
    });
  });
}

function cleanup() {
  splits.forEach((split) => split.revert());
  splits.length = 0;
}
清理事件监听器
// Use AbortController for easy cleanup
const controller = new AbortController();

window.addEventListener("resize", handleResize, {
  signal: controller.signal,
});

window.addEventListener("scroll", handleScroll, {
  passive: true,
  signal: controller.signal,
});

// Cleanup all at once
function cleanup() {
  controller.abort();
}

调试清单

性能问题
  1. 丢帧?

    • 检查 DevTools Performance 面板
    • 查找长任务(> 50ms)
    • 确认动画仅涉及合成器属性
  2. 初始加载缓慢?

    • 检查 Network 瀑布图
    • 确认关键路径已优化
    • 检查 Bundle 大小
  3. 内存泄漏?

    • 随时间检查 Memory 面板
    • 确认导航时会执行清理
    • 留意已分离的 DOM 节点
  4. 布局抖动?

    • 在 Performance 面板中查找强制重排
    • 批量执行 DOM 读取/写入
    • 使用 transform 代替 position
快速检查
// Log animation frame rate
let lastTime = performance.now();
let frameCount = 0;

function measureFPS() {
  frameCount++;
  const now = performance.now();
  if (now - lastTime >= 1000) {
    console.log("FPS:", frameCount);
    frameCount = 0;
    lastTime = now;
  }
  requestAnimationFrame(measureFPS);
}
measureFPS();
// Detect layout thrashing
const originalGetComputedStyle = window.getComputedStyle;
window.getComputedStyle = function (...args) {
  console.trace("getComputedStyle called");
  return originalGetComputedStyle.apply(this, args);
};

如需了解全面的调试技巧,请参阅 debugging.md。


资源

评论

支持 Markdown