mcpField
P
performance

performance

github.com/davila7开发33.0k212 次安装今天更新
代码仓库

关于 performance

此技能根据 Lighthouse 审计提供 Web 性能优化指导,帮助开发者定位瓶颈、按 Core Web Vitals 确定优先级,并通过前后指标评估代码和资源调整。

主要功能

  1. 01定位代码和资源瓶颈
  2. 02按 Core Web Vitals 排序
  3. 03优化加载与渲染
  4. 04提升运行时效率
  5. 05测量优化前后效果

适用场景

  1. 01诊断页面加载缓慢
  2. 02降低 JavaScript 和资源开销
  3. 03改善渲染与交互性能
  4. 04用 Lighthouse 指标评估改动

安装

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

$npx skills add https://github.com/davila7/claude-code-templates --skill performance

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

详细介绍

性能优化

基于 Lighthouse 性能审计进行深入的性能优化,重点关注加载速度、运行时效率和资源优化。

工作原理

  1. 识别代码和资源中的性能瓶颈
  2. 根据对 Core Web Vitals 的影响确定优先级
  3. 提供具体的优化方案和代码示例
  4. 使用优化前后的指标衡量改进效果

性能预算

资源预算原因
页面总大小< 1.5 MB3G 网络下约 4 秒加载完成
JavaScript(压缩后)< 300 KB解析和执行耗时
CSS(压缩后)< 100 KB阻塞渲染
图片(首屏)< 500 KB影响 LCP
字体< 100 KB防止 FOIT/FOUT
第三方资源< 200 KB延迟不可控

关键渲染路径

服务器响应
  • TTFB < 800ms。 首字节时间应尽可能短。使用 CDN、缓存和高效的后端。
  • 启用压缩。 对文本资源使用 Gzip 或 Brotli。优先使用 Brotli(体积小 15-20%)。
  • HTTP/2 或 HTTP/3。 多路复用可减少连接开销。
  • 边缘缓存。 尽可能在 CDN 边缘缓存 HTML。
资源加载

预连接到所需的源:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

预加载关键资源:


<link rel="preload" href="/hero.webp" as="image" fetchpriority="high">


<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>

延迟加载非关键 CSS:


<style>/* Above-fold styles */</style>


<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
JavaScript 优化

延迟加载非必要脚本:


<script src="/critical.js"></script>


<script defer src="/app.js"></script>


<script async src="/analytics.js"></script>


<script type="module" src="/app.mjs"></script>

代码拆分模式:

// Route-based splitting
const Dashboard = lazy(() => import('./Dashboard'));

// Component-based splitting
const HeavyChart = lazy(() => import('./HeavyChart'));

// Feature-based splitting
if (user.isPremium) {
  const PremiumFeatures = await import('./PremiumFeatures');
}

Tree shaking 最佳实践:

// ❌ Imports entire library
import _ from 'lodash';
_.debounce(fn, 300);

// ✅ Imports only what's needed
import debounce from 'lodash/debounce';
debounce(fn, 300);

图片优化

格式选择
格式使用场景浏览器支持率
AVIF照片,压缩效果最佳92%+
WebP照片,良好的后备格式97%+
PNG带透明背景的图形通用
SVG图标、徽标、插画通用
响应式图片
<picture>
  
  <source 
    type="image/avif"
    srcset="hero-400.avif 400w,
            hero-800.avif 800w,
            hero-1200.avif 1200w"
    sizes="(max-width: 600px) 100vw, 50vw">
  
  
  <source 
    type="image/webp"
    srcset="hero-400.webp 400w,
            hero-800.webp 800w,
            hero-1200.webp 1200w"
    sizes="(max-width: 600px) 100vw, 50vw">
  
  
  <img 
    src="hero-800.jpg"
    srcset="hero-400.jpg 400w,
            hero-800.jpg 800w,
            hero-1200.jpg 1200w"
    sizes="(max-width: 600px) 100vw, 50vw"
    width="1200" 
    height="600"
    alt="Hero image"
    loading="lazy"
    decoding="async">
</picture>
LCP 图片优先级

<img 
  src="hero.webp" 
  fetchpriority="high"
  loading="eager"
  decoding="sync"
  alt="Hero">


<img 
  src="product.webp" 
  loading="lazy"
  decoding="async"
  alt="Product">

字体优化

加载策略
/* System font stack as fallback */
body {
  font-family: 'Custom Font', -apple-system, BlinkMacSystemFont, 
               'Segoe UI', Roboto, sans-serif;
}

/* Prevent invisible text */
@font-face {
  font-family: 'Custom Font';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap; /* or optional for non-critical */
  font-weight: 400;
  font-style: normal;
  unicode-range: U+0000-00FF; /* Subset to Latin */
}
预加载关键字体
<link rel="preload" href="/fonts/heading.woff2" as="font" type="font/woff2" crossorigin>
可变字体
/* One file instead of multiple weights */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

缓存策略

Cache-Control 标头
# HTML (short or no cache)
Cache-Control: no-cache, must-revalidate

# Static assets with hash (immutable)
Cache-Control: public, max-age=31536000, immutable

# Static assets without hash
Cache-Control: public, max-age=86400, stale-while-revalidate=604800

# API responses
Cache-Control: private, max-age=0, must-revalidate
Service Worker 缓存
// Cache-first for static assets
self.addEventListener('fetch', (event) => {
  if (event.request.destination === 'image' ||
      event.request.destination === 'style' ||
      event.request.destination === 'script') {
    event.respondWith(
      caches.match(event.request).then((cached) => {
        return cached || fetch(event.request).then((response) => {
          const clone = response.clone();
          caches.open('static-v1').then((cache) => cache.put(event.request, clone));
          return response;
        });
      })
    );
  }
});

运行时性能

避免布局抖动
// ❌ Forces multiple reflows
elements.forEach(el => {
  const height = el.offsetHeight; // Read
  el.style.height = height + 10 + 'px'; // Write
});

// ✅ Batch reads, then batch writes
const heights = elements.map(el => el.offsetHeight); // All reads
elements.forEach((el, i) => {
  el.style.height = heights[i] + 10 + 'px'; // All writes
});
对耗时操作进行防抖处理
function debounce(fn, delay) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

// Debounce scroll/resize handlers
window.addEventListener('scroll', debounce(handleScroll, 100));
使用 requestAnimationFrame
// ❌ May cause jank
setInterval(animate, 16);

// ✅ Synced with display refresh
function animate() {
  // Animation logic
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
对长列表进行虚拟化
// For lists > 100 items, render only visible items
// Use libraries like react-window, vue-virtual-scroller, or native CSS:
.virtual-list {
  content-visibility: auto;
  contain-intrinsic-size: 0 50px; /* Estimated item height */
}

第三方脚本

加载策略
// ❌ Blocks main thread
<script src="https://analytics.example.com/script.js"></script>

// ✅ Async loading
<script async src="https://analytics.example.com/script.js"></script>

// ✅ Delay until interaction
<script>
document.addEventListener('DOMContentLoaded', () => {
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
      const script = document.createElement('script');
      script.src = 'https://widget.example.com/embed.js';
      document.body.appendChild(script);
      observer.disconnect();
    }
  });
  observer.observe(document.querySelector('#widget-container'));
});
</script>
门面模式

<div class="youtube-facade" 
     data-video-id="abc123" 
     onclick="loadYouTube(this)">
  <img src="/thumbnails/abc123.jpg" alt="Video title">
  <button aria-label="Play video">▶</button>
</div>

测量

关键指标
指标目标工具
LCP< 2.5sLighthouse、CrUX
FCP< 1.8sLighthouse
Speed Index< 3.4sLighthouse
TBT< 200msLighthouse
TTI< 3.8sLighthouse
测试命令
# Lighthouse CLI
npx lighthouse https://example.com --output html --output-path report.html

# Web Vitals library
import {onLCP, onINP, onCLS} from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);

参考资料

有关 Core Web Vitals 的特定优化,请参阅 Core Web Vitals。

评论

支持 Markdown