Files
2025-11-30 08:47:23 +08:00

5.5 KiB

name, description
name description
perf-analyzer WHEN: Performance analysis, bundle size optimization, rendering, Core Web Vitals, code splitting WHAT: Bundle analysis + large dependency detection + re-render issues + useMemo/useCallback suggestions + LCP/FID/CLS improvements WHEN NOT: Code quality → code-reviewer, Security → security-scanner

Performance Analyzer Skill

Purpose

Analyzes frontend application performance and suggests optimizations for bundle size, rendering, and images.

When to Use

  • Performance analysis requests
  • "Slow", "long loading" mentions
  • Bundle size, rendering, Core Web Vitals questions
  • Pre-production performance review

Workflow

Step 1: Select Analysis Areas

AskUserQuestion:

"Which areas to analyze?"
Options:
- Full performance analysis (recommended)
- Bundle size analysis
- Rendering performance (re-renders)
- Image/asset optimization
- Code splitting opportunities
multiSelect: true

Analysis Areas

Bundle Size

Item Threshold Severity
Total bundle > 500KB HIGH
Initial JS > 200KB HIGH
Single chunk > 100KB MEDIUM
Unused code Tree-shaking failures MEDIUM

Large Dependencies:

// WARNING: Large libraries
import _ from 'lodash'         // 71KB
import moment from 'moment'    // 280KB

// BETTER: Lightweight alternatives
import debounce from 'lodash/debounce'  // 2KB
import { format } from 'date-fns'        // Only needed functions

Tree-shaking Issues:

// BAD: Full import (no tree-shaking)
import * as utils from './utils'

// GOOD: Named import
import { specificFunction } from './utils'

Rendering Performance

Unnecessary Re-renders:

// WARNING: New object/array every render
function Component() {
  return <Child style={{ color: 'red' }} />  // New object each time
}

// BETTER: External definition
const style = { color: 'red' }
function Component() {
  return <Child style={style} />
}

Expensive Computations:

// WARNING: Computed every render
function Component({ data }) {
  const processed = data.map(item => expensiveOp(item))
  return <List items={processed} />
}

// BETTER: useMemo caching
const processed = useMemo(
  () => data.map(item => expensiveOp(item)),
  [data]
)

Callback Optimization:

// WARNING: New function every render
<Child onClick={() => handleClick()} />

// BETTER: useCallback
const handleClick = useCallback(() => { /* ... */ }, [])
<Child onClick={handleClick} />

Image Optimization

Issue Problem Solution
Large image > 200KB Compress or WebP
Unoptimized format PNG/JPG WebP/AVIF
Missing lazy load Offscreen images loading="lazy"
Fixed size Non-responsive srcset/sizes
// BAD: No optimization
<img src="/hero.jpg" alt="Hero" />

// GOOD: next/image
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority  // LCP image
  placeholder="blur"
/>

Code Splitting

// WARNING: Unnecessary initial load
import HeavyComponent from './HeavyComponent'

// BETTER: Load on demand
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <Skeleton />
})

Core Web Vitals

LCP (Largest Contentful Paint)

Grade Time Improvements
Good < 2.5s -
Needs Work 2.5-4s Image optimization, server response
Poor > 4s CDN, caching, code splitting

FID (First Input Delay)

Grade Time Improvements
Good < 100ms -
Needs Work 100-300ms Reduce main thread blocking
Poor > 300ms Split long tasks, Web Workers

CLS (Cumulative Layout Shift)

Grade Score Improvements
Good < 0.1 -
Needs Work 0.1-0.25 Specify image/font dimensions
Poor > 0.25 Reserve space for dynamic content

Response Template

## Performance Analysis Results

**Project**: [name]

### Bundle Size
| Item | Size | Status |
|------|------|--------|
| Total bundle | 650KB | WARNING |
| Initial JS | 180KB | OK |

**Large Dependencies:**
| Package | Size | Alternative |
|---------|------|-------------|
| moment | 280KB | date-fns (7KB) |
| lodash | 71KB | lodash-es + individual imports |

### Rendering Performance
| Component | Issue | Recommendation |
|-----------|-------|----------------|
| ProductList | Unnecessary re-renders | Add useMemo |

### Image Optimization
| Image | Size | Recommendation |
|-------|------|----------------|
| hero.jpg | 450KB | Convert to WebP, use next/image |

### Code Splitting Opportunities
| Component | Size | Recommendation |
|-----------|------|----------------|
| Dashboard | 85KB | dynamic import |

### Priority Actions
1. [ ] moment → date-fns migration (-273KB)
2. [ ] Add useMemo to ProductList
3. [ ] Convert hero.jpg to WebP
4. [ ] Dynamic import Dashboard

### Expected Improvements
- Initial bundle: 650KB → ~350KB (-46%)
- LCP: Expected improvement
- TTI: Expected improvement

Best Practices

  1. Measure First: Always measure before optimizing
  2. Incremental: Apply one change at a time
  3. Trade-offs: Avoid over-optimization
  4. Real Device Testing: Test on low-end devices
  5. Continuous Monitoring: Prevent performance regression

Integration

  • code-reviewer skill
  • nextjs-reviewer skill
  • /analyze-code command

Notes

  • Static analysis based, runtime performance may differ
  • Use with Lighthouse for actual measurements
  • Analyze production builds