--- name: perf-analyzer description: | 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:** ```typescript // 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:** ```typescript // BAD: Full import (no tree-shaking) import * as utils from './utils' // GOOD: Named import import { specificFunction } from './utils' ``` ### Rendering Performance **Unnecessary Re-renders:** ```typescript // WARNING: New object/array every render function Component() { return // New object each time } // BETTER: External definition const style = { color: 'red' } function Component() { return } ``` **Expensive Computations:** ```typescript // WARNING: Computed every render function Component({ data }) { const processed = data.map(item => expensiveOp(item)) return } // BETTER: useMemo caching const processed = useMemo( () => data.map(item => expensiveOp(item)), [data] ) ``` **Callback Optimization:** ```typescript // WARNING: New function every render handleClick()} /> // BETTER: useCallback const handleClick = useCallback(() => { /* ... */ }, []) ``` ### 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 | ```typescript // BAD: No optimization Hero // GOOD: next/image Hero ``` ### Code Splitting ```typescript // WARNING: Unnecessary initial load import HeavyComponent from './HeavyComponent' // BETTER: Load on demand const HeavyComponent = dynamic(() => import('./HeavyComponent'), { loading: () => }) ``` ### 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