Vibeship-spawner-skills performance-optimization

Performance Optimization Skill

install
source · Clone the upstream repo
git clone https://github.com/vibeforge1111/vibeship-spawner-skills
manifest: development/performance-optimization/skill.yaml
source content

Performance 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