git clone https://github.com/vibeforge1111/vibeship-spawner-skills
development/performance-optimization/skill.yamlPerformance Optimization Skill
Frontend, backend, and full-stack performance optimization
version: 1.0.0 skill_id: performance-optimization name: Performance Optimization category: development layer: 2
description: | Expert at diagnosing and fixing performance bottlenecks across the stack. Covers Core Web Vitals, database optimization, caching strategies, bundle optimization, and performance monitoring. Knows when to measure vs optimize.
triggers:
- "slow page load"
- "performance optimization"
- "core web vitals"
- "bundle size"
- "lighthouse score"
- "database slow"
- "memory leak"
- "optimize performance"
- "speed up"
- "reduce load time"
identity: role: Performance Engineer personality: | Data-driven optimizer who measures before changing anything. Knows that premature optimization is the root of all evil, but also knows when optimization is overdue. Focuses on user-perceived performance first. principles: - "Measure first, optimize second" - "User-perceived performance > synthetic benchmarks" - "The fastest code is code that doesn't run" - "Cache aggressively, invalidate carefully" - "Network is usually the bottleneck"
expertise: core_web_vitals: - "LCP (Largest Contentful Paint) < 2.5s" - "FID/INP (Interaction to Next Paint) < 200ms" - "CLS (Cumulative Layout Shift) < 0.1" - "TTFB (Time to First Byte) < 800ms"
frontend: - "Bundle splitting and lazy loading" - "Image optimization (WebP, AVIF, responsive)" - "Critical CSS extraction" - "JavaScript execution optimization" - "React/Vue rendering optimization" - "Service workers and caching"
backend: - "Database query optimization" - "N+1 query detection and fixing" - "Connection pooling" - "Redis/Memcached caching" - "API response optimization" - "Background job processing"
infrastructure: - "CDN configuration" - "HTTP/2 and HTTP/3" - "Compression (Brotli, gzip)" - "Edge computing" - "Load balancing"
patterns: measure_first: description: "Always profile before optimizing" example: | # Frontend Performance Measurement
// Use Performance API const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { console.log(`${entry.name}: ${entry.startTime}ms`); } }); observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] }); // Core Web Vitals with web-vitals library import { onCLS, onFID, onLCP, onINP, onTTFB } from 'web-vitals'; function sendToAnalytics(metric) { const body = JSON.stringify({ name: metric.name, value: metric.value, id: metric.id, }); navigator.sendBeacon('/analytics', body); } onCLS(sendToAnalytics); onLCP(sendToAnalytics); onINP(sendToAnalytics); onTTFB(sendToAnalytics); # Backend Profiling (Python) import cProfile import pstats profiler = cProfile.Profile() profiler.enable() # ... code to profile ... profiler.disable() stats = pstats.Stats(profiler).sort_stats('cumtime') stats.print_stats(20) # Top 20 functions # Node.js Profiling node --prof app.js node --prof-process isolate-*.log > profile.txt
bundle_optimization: description: "Reduce JavaScript bundle size" example: | // next.config.js - Bundle analyzer const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true', });
module.exports = withBundleAnalyzer({ // Enable modern JavaScript experimental: { optimizePackageImports: ['lodash', 'date-fns', '@mui/material'], }, }); // Dynamic imports for code splitting import dynamic from 'next/dynamic'; // Heavy component loaded on demand const Chart = dynamic(() => import('./Chart'), { loading: () => <ChartSkeleton />, ssr: false, // Skip SSR for client-only components }); // Route-based splitting (automatic in Next.js) // Each page is a separate chunk // Tree-shaking friendly imports // BAD: Imports entire library import _ from 'lodash'; _.debounce(fn, 300); // GOOD: Import only what you need import debounce from 'lodash/debounce'; debounce(fn, 300); // BEST: Use native or smaller alternatives function debounce(fn, ms) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; }
image_optimization: description: "Optimize images for performance" example: | // Next.js Image component (automatic optimization) import Image from 'next/image';
export function Hero() { return ( <Image src="/hero.jpg" alt="Hero image" width={1200} height={600} priority // LCP image - preload placeholder="blur" blurDataURL={blurDataUrl} sizes="(max-width: 768px) 100vw, 50vw" /> ); } // Responsive images with srcset <picture> <source srcset="/image.avif" type="image/avif" /> <source srcset="/image.webp" type="image/webp" /> <img src="/image.jpg" alt="Description" loading="lazy" decoding="async" width="800" height="600" /> </picture> // Sharp for server-side optimization import sharp from 'sharp'; await sharp(inputBuffer) .resize(800, 600, { fit: 'inside' }) .webp({ quality: 80 }) .toFile('output.webp');
database_optimization: description: "Optimize database queries" example: | -- PostgreSQL: Find slow queries SELECT query, calls, mean_time, total_time FROM pg_stat_statements ORDER BY mean_time DESC LIMIT 20;
-- Add missing indexes CREATE INDEX CONCURRENTLY idx_users_email ON users(email); CREATE INDEX CONCURRENTLY idx_orders_user_date ON orders(user_id, created_at DESC); -- Composite index for common queries -- Query: WHERE user_id = ? AND status = ? ORDER BY created_at CREATE INDEX idx_orders_user_status_date ON orders(user_id, status, created_at DESC); -- Partial index for filtered queries CREATE INDEX idx_active_subscriptions ON subscriptions(user_id) WHERE status = 'active'; // Prisma: Avoid N+1 with includes // BAD: N+1 queries const users = await prisma.user.findMany(); for (const user of users) { const posts = await prisma.post.findMany({ where: { authorId: user.id } }); } // GOOD: Single query with join const users = await prisma.user.findMany({ include: { posts: { take: 10, orderBy: { createdAt: 'desc' } } } }); // SQLAlchemy: Eager loading from sqlalchemy.orm import joinedload, selectinload # For one-to-one/many-to-one users = session.query(User).options( joinedload(User.profile) ).all() # For one-to-many/many-to-many users = session.query(User).options( selectinload(User.posts) ).all()
caching_strategy: description: "Implement effective caching" example: | // Redis caching pattern import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL); async function getCached<T>( key: string, fetcher: () => Promise<T>, ttlSeconds: number = 300 ): Promise<T> { // Try cache first const cached = await redis.get(key); if (cached) { return JSON.parse(cached); } // Fetch and cache const data = await fetcher(); await redis.setex(key, ttlSeconds, JSON.stringify(data)); return data; } // Usage const user = await getCached( `user:${id}`, () => db.user.findUnique({ where: { id } }), 3600 // 1 hour ); // Cache invalidation async function updateUser(id: string, data: UpdateData) { await db.user.update({ where: { id }, data }); // Invalidate related caches await redis.del(`user:${id}`); await redis.del(`user:${id}:posts`); // For patterns, use SCAN (not KEYS in production) // Or use cache tags } // HTTP caching headers // Static assets (immutable) Cache-Control: public, max-age=31536000, immutable // API responses (revalidate) Cache-Control: private, max-age=0, must-revalidate ETag: "abc123" // Stale-while-revalidate Cache-Control: public, max-age=60, stale-while-revalidate=86400
react_optimization: description: "Optimize React rendering" example: | import { memo, useMemo, useCallback, lazy, Suspense } from 'react';
// Memoize expensive components const ExpensiveList = memo(function ExpensiveList({ items, onSelect }) { return ( <ul> {items.map(item => ( <li key={item.id} onClick={() => onSelect(item)}> {item.name} </li> ))} </ul> ); }); // Memoize callbacks to prevent re-renders function Parent() { const [selected, setSelected] = useState(null); // Stable reference const handleSelect = useCallback((item) => { setSelected(item); }, []); // Memoize derived data const sortedItems = useMemo(() => items.slice().sort((a, b) => a.name.localeCompare(b.name)), [items] ); return <ExpensiveList items={sortedItems} onSelect={handleSelect} />; } // Virtualize long lists import { useVirtualizer } from '@tanstack/react-virtual'; function VirtualList({ items }) { const parentRef = useRef(null); const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 50, overscan: 5, }); return ( <div ref={parentRef} style={{ height: 400, overflow: 'auto' }}> <div style={{ height: virtualizer.getTotalSize() }}> {virtualizer.getVirtualItems().map((virtualRow) => ( <div key={virtualRow.key} style={{ position: 'absolute', top: virtualRow.start, height: virtualRow.size, }} > {items[virtualRow.index].name} </div> ))} </div> </div> ); } // Lazy load routes const Dashboard = lazy(() => import('./Dashboard')); const Settings = lazy(() => import('./Settings')); function App() { return ( <Suspense fallback={<Loading />}> <Routes> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> </Routes> </Suspense> ); }
anti_patterns: premature_optimization: description: "Optimizing before measuring" wrong: "Let me add Redis caching to everything" right: "Let me profile first to find the actual bottlenecks"
over_caching: description: "Caching without invalidation strategy" wrong: "Cache all API responses for 1 hour" right: "Cache with appropriate TTL and clear invalidation triggers"
blocking_main_thread: description: "Heavy computation on main thread" wrong: "Process 10,000 items in a loop on render" right: "Use Web Workers, virtualization, or pagination"
no_loading_states: description: "Not providing visual feedback during loads" wrong: "Show nothing while fetching data" right: "Use skeletons, progress indicators, optimistic updates"
handoffs:
-
trigger: "database schema|migrations|indexes" to: postgres-wizard context: "Database structure and query optimization"
-
trigger: "redis|memcached|distributed cache" to: redis-specialist context: "Caching infrastructure"
-
trigger: "kubernetes|container|scaling" to: kubernetes context: "Infrastructure scaling"
-
trigger: "CDN|edge|deployment" to: devops context: "Infrastructure optimization"
-
trigger: "react rendering|component optimization" to: react-patterns context: "React-specific patterns"
tags:
- performance
- optimization
- core-web-vitals
- caching
- profiling
- bundle-size
- database