Optimize website and web application performance including loading speed, Core Web Vitals, bundle size, caching strategies, and runtime performance
Add this skill
npx mdskills install sickn33/web-performance-optimizationComprehensive, well-structured guide with excellent examples and actionable optimization steps
1---2name: web-performance-optimization3description: "Optimize website and web application performance including loading speed, Core Web Vitals, bundle size, caching strategies, and runtime performance"4---56# Web Performance Optimization78## Overview910Help developers optimize website and web application performance to improve user experience, SEO rankings, and conversion rates. This skill provides systematic approaches to measure, analyze, and improve loading speed, runtime performance, and Core Web Vitals metrics.1112## When to Use This Skill1314- Use when website or app is loading slowly15- Use when optimizing for Core Web Vitals (LCP, FID, CLS)16- Use when reducing JavaScript bundle size17- Use when improving Time to Interactive (TTI)18- Use when optimizing images and assets19- Use when implementing caching strategies20- Use when debugging performance bottlenecks21- Use when preparing for performance audits2223## How It Works2425### Step 1: Measure Current Performance2627I'll help you establish baseline metrics:28- Run Lighthouse audits29- Measure Core Web Vitals (LCP, FID, CLS)30- Check bundle sizes31- Analyze network waterfall32- Identify performance bottlenecks3334### Step 2: Identify Issues3536Analyze performance problems:37- Large JavaScript bundles38- Unoptimized images39- Render-blocking resources40- Slow server response times41- Missing caching headers42- Layout shifts43- Long tasks blocking main thread4445### Step 3: Prioritize Optimizations4647Focus on high-impact improvements:48- Critical rendering path optimization49- Code splitting and lazy loading50- Image optimization51- Caching strategies52- Third-party script optimization5354### Step 4: Implement Optimizations5556Apply performance improvements:57- Optimize assets (images, fonts, CSS, JS)58- Implement code splitting59- Add caching headers60- Lazy load non-critical resources61- Optimize critical rendering path6263### Step 5: Verify Improvements6465Measure impact of changes:66- Re-run Lighthouse audits67- Compare before/after metrics68- Monitor real user metrics (RUM)69- Test on different devices and networks7071## Examples7273### Example 1: Optimizing Core Web Vitals7475```markdown76## Performance Audit Results7778### Current Metrics (Before Optimization)79- **LCP (Largest Contentful Paint):** 4.2s ❌ (should be < 2.5s)80- **FID (First Input Delay):** 180ms ❌ (should be < 100ms)81- **CLS (Cumulative Layout Shift):** 0.25 ❌ (should be < 0.1)82- **Lighthouse Score:** 62/1008384### Issues Identified85861. **LCP Issue:** Hero image (2.5MB) loads slowly872. **FID Issue:** Large JavaScript bundle (850KB) blocks main thread883. **CLS Issue:** Images without dimensions cause layout shifts8990### Optimization Plan9192#### Fix LCP (Largest Contentful Paint)9394**Problem:** Hero image is 2.5MB and loads slowly9596**Solutions:**97\`\`\`html98<!-- Before: Unoptimized image -->99<img src="/hero.jpg" alt="Hero">100101<!-- After: Optimized with modern formats -->102<picture>103 <source srcset="/hero.avif" type="image/avif">104 <source srcset="/hero.webp" type="image/webp">105 <img106 src="/hero.jpg"107 alt="Hero"108 width="1200"109 height="600"110 loading="eager"111 fetchpriority="high"112 >113</picture>114\`\`\`115116**Additional optimizations:**117- Compress image to < 200KB118- Use CDN for faster delivery119- Preload hero image: `<link rel="preload" as="image" href="/hero.avif">`120121#### Fix FID (First Input Delay)122123**Problem:** 850KB JavaScript bundle blocks main thread124125**Solutions:**1261271. **Code Splitting:**128\`\`\`javascript129// Before: Everything in one bundle130import { HeavyComponent } from './HeavyComponent';131import { Analytics } from './analytics';132import { ChatWidget } from './chat';133134// After: Lazy load non-critical code135const HeavyComponent = lazy(() => import('./HeavyComponent'));136const ChatWidget = lazy(() => import('./chat'));137138// Load analytics after page interactive139if (typeof window !== 'undefined') {140 window.addEventListener('load', () => {141 import('./analytics').then(({ Analytics }) => {142 Analytics.init();143 });144 });145}146\`\`\`1471482. **Remove Unused Dependencies:**149\`\`\`bash150# Analyze bundle151npx webpack-bundle-analyzer152153# Remove unused packages154npm uninstall moment # Use date-fns instead (smaller)155npm install date-fns156\`\`\`1571583. **Defer Non-Critical Scripts:**159\`\`\`html160<!-- Before: Blocks rendering -->161<script src="/analytics.js"></script>162163<!-- After: Deferred -->164<script src="/analytics.js" defer></script>165\`\`\`166167#### Fix CLS (Cumulative Layout Shift)168169**Problem:** Images without dimensions cause layout shifts170171**Solutions:**172\`\`\`html173<!-- Before: No dimensions -->174<img src="/product.jpg" alt="Product">175176<!-- After: With dimensions -->177<img178 src="/product.jpg"179 alt="Product"180 width="400"181 height="300"182 style="aspect-ratio: 4/3;"183>184\`\`\`185186**For dynamic content:**187\`\`\`css188/* Reserve space for content that loads later */189.skeleton-loader {190 min-height: 200px;191 background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);192 background-size: 200% 100%;193 animation: loading 1.5s infinite;194}195196@keyframes loading {197 0% { background-position: 200% 0; }198 100% { background-position: -200% 0; }199}200\`\`\`201202### Results After Optimization203204- **LCP:** 1.8s ✅ (improved by 57%)205- **FID:** 45ms ✅ (improved by 75%)206- **CLS:** 0.05 ✅ (improved by 80%)207- **Lighthouse Score:** 94/100 ✅208```209210### Example 2: Reducing JavaScript Bundle Size211212```markdown213## Bundle Size Optimization214215### Current State216- **Total Bundle:** 850KB (gzipped: 280KB)217- **Main Bundle:** 650KB218- **Vendor Bundle:** 200KB219- **Load Time (3G):** 8.2s220221### Analysis222223\`\`\`bash224# Analyze bundle composition225npx webpack-bundle-analyzer dist/stats.json226\`\`\`227228**Findings:**2291. Moment.js: 67KB (can replace with date-fns: 12KB)2302. Lodash: 72KB (using entire library, only need 5 functions)2313. Unused code: ~150KB of dead code2324. No code splitting: Everything in one bundle233234### Optimization Steps235236#### 1. Replace Heavy Dependencies237238\`\`\`bash239# Remove moment.js (67KB) → Use date-fns (12KB)240npm uninstall moment241npm install date-fns242243# Before244import moment from 'moment';245const formatted = moment(date).format('YYYY-MM-DD');246247# After248import { format } from 'date-fns';249const formatted = format(date, 'yyyy-MM-dd');250\`\`\`251252**Savings:** 55KB253254#### 2. Use Lodash Selectively255256\`\`\`javascript257// Before: Import entire library (72KB)258import _ from 'lodash';259const unique = _.uniq(array);260261// After: Import only what you need (5KB)262import uniq from 'lodash/uniq';263const unique = uniq(array);264265// Or use native methods266const unique = [...new Set(array)];267\`\`\`268269**Savings:** 67KB270271#### 3. Implement Code Splitting272273\`\`\`javascript274// Next.js example275import dynamic from 'next/dynamic';276277// Lazy load heavy components278const Chart = dynamic(() => import('./Chart'), {279 loading: () => <div>Loading chart...</div>,280 ssr: false281});282283const AdminPanel = dynamic(() => import('./AdminPanel'), {284 loading: () => <div>Loading...</div>285});286287// Route-based code splitting (automatic in Next.js)288// pages/admin.js - Only loaded when visiting /admin289// pages/dashboard.js - Only loaded when visiting /dashboard290\`\`\`291292#### 4. Remove Dead Code293294\`\`\`javascript295// Enable tree shaking in webpack.config.js296module.exports = {297 mode: 'production',298 optimization: {299 usedExports: true,300 sideEffects: false301 }302};303304// In package.json305{306 "sideEffects": false307}308\`\`\`309310#### 5. Optimize Third-Party Scripts311312\`\`\`html313<!-- Before: Loads immediately -->314<script src="https://analytics.com/script.js"></script>315316<!-- After: Load after page interactive -->317<script>318 window.addEventListener('load', () => {319 const script = document.createElement('script');320 script.src = 'https://analytics.com/script.js';321 script.async = true;322 document.body.appendChild(script);323 });324</script>325\`\`\`326327### Results328329- **Total Bundle:** 380KB ✅ (reduced by 55%)330- **Main Bundle:** 180KB ✅331- **Vendor Bundle:** 80KB ✅332- **Load Time (3G):** 3.1s ✅ (improved by 62%)333```334335### Example 3: Image Optimization Strategy336337```markdown338## Image Optimization339340### Current Issues341- 15 images totaling 12MB342- No modern formats (WebP, AVIF)343- No responsive images344- No lazy loading345346### Optimization Strategy347348#### 1. Convert to Modern Formats349350\`\`\`bash351# Install image optimization tools352npm install sharp353354# Conversion script (optimize-images.js)355const sharp = require('sharp');356const fs = require('fs');357const path = require('path');358359async function optimizeImage(inputPath, outputDir) {360 const filename = path.basename(inputPath, path.extname(inputPath));361362 // Generate WebP363 await sharp(inputPath)364 .webp({ quality: 80 })365 .toFile(path.join(outputDir, \`\${filename}.webp\`));366367 // Generate AVIF (best compression)368 await sharp(inputPath)369 .avif({ quality: 70 })370 .toFile(path.join(outputDir, \`\${filename}.avif\`));371372 // Generate optimized JPEG fallback373 await sharp(inputPath)374 .jpeg({ quality: 80, progressive: true })375 .toFile(path.join(outputDir, \`\${filename}.jpg\`));376}377378// Process all images379const images = fs.readdirSync('./images');380images.forEach(img => {381 optimizeImage(\`./images/\${img}\`, './images/optimized');382});383\`\`\`384385#### 2. Implement Responsive Images386387\`\`\`html388<!-- Responsive images with modern formats -->389<picture>390 <!-- AVIF for browsers that support it (best compression) -->391 <source392 srcset="393 /images/hero-400.avif 400w,394 /images/hero-800.avif 800w,395 /images/hero-1200.avif 1200w396 "397 type="image/avif"398 sizes="(max-width: 768px) 100vw, 50vw"399 >400401 <!-- WebP for browsers that support it -->402 <source403 srcset="404 /images/hero-400.webp 400w,405 /images/hero-800.webp 800w,406 /images/hero-1200.webp 1200w407 "408 type="image/webp"409 sizes="(max-width: 768px) 100vw, 50vw"410 >411412 <!-- JPEG fallback -->413 <img414 src="/images/hero-800.jpg"415 srcset="416 /images/hero-400.jpg 400w,417 /images/hero-800.jpg 800w,418 /images/hero-1200.jpg 1200w419 "420 sizes="(max-width: 768px) 100vw, 50vw"421 alt="Hero image"422 width="1200"423 height="600"424 loading="lazy"425 >426</picture>427\`\`\`428429#### 3. Lazy Loading430431\`\`\`html432<!-- Native lazy loading -->433<img434 src="/image.jpg"435 alt="Description"436 loading="lazy"437 width="800"438 height="600"439>440441<!-- Eager loading for above-the-fold images -->442<img443 src="/hero.jpg"444 alt="Hero"445 loading="eager"446 fetchpriority="high"447>448\`\`\`449450#### 4. Next.js Image Component451452\`\`\`javascript453import Image from 'next/image';454455// Automatic optimization456<Image457 src="/hero.jpg"458 alt="Hero"459 width={1200}460 height={600}461 priority // For above-the-fold images462 quality={80}463/>464465// Lazy loaded466<Image467 src="/product.jpg"468 alt="Product"469 width={400}470 height={300}471 loading="lazy"472/>473\`\`\`474475### Results476477| Metric | Before | After | Improvement |478|--------|--------|-------|-------------|479| Total Image Size | 12MB | 1.8MB | 85% reduction |480| LCP | 4.5s | 1.6s | 64% faster |481| Page Load (3G) | 18s | 4.2s | 77% faster |482```483484## Best Practices485486### ✅ Do This487488- **Measure First** - Always establish baseline metrics before optimizing489- **Use Lighthouse** - Run audits regularly to track progress490- **Optimize Images** - Use modern formats (WebP, AVIF) and responsive images491- **Code Split** - Break large bundles into smaller chunks492- **Lazy Load** - Defer non-critical resources493- **Cache Aggressively** - Set proper cache headers for static assets494- **Minimize Main Thread Work** - Keep JavaScript execution under 50ms chunks495- **Preload Critical Resources** - Use `<link rel="preload">` for critical assets496- **Use CDN** - Serve static assets from CDN for faster delivery497- **Monitor Real Users** - Track Core Web Vitals from real users498499### ❌ Don't Do This500501- **Don't Optimize Blindly** - Measure first, then optimize502- **Don't Ignore Mobile** - Test on real mobile devices and slow networks503- **Don't Block Rendering** - Avoid render-blocking CSS and JavaScript504- **Don't Load Everything Upfront** - Lazy load non-critical resources505- **Don't Forget Dimensions** - Always specify image width/height506- **Don't Use Synchronous Scripts** - Use async or defer attributes507- **Don't Ignore Third-Party Scripts** - They often cause performance issues508- **Don't Skip Compression** - Always compress and minify assets509510## Common Pitfalls511512### Problem: Optimized for Desktop but Slow on Mobile513**Symptoms:** Good Lighthouse score on desktop, poor on mobile514**Solution:**515- Test on real mobile devices516- Use Chrome DevTools mobile throttling517- Optimize for 3G/4G networks518- Reduce JavaScript execution time519```bash520# Test with throttling521lighthouse https://yoursite.com --throttling.cpuSlowdownMultiplier=4522```523524### Problem: Large JavaScript Bundle525**Symptoms:** Long Time to Interactive (TTI), high FID526**Solution:**527- Analyze bundle with webpack-bundle-analyzer528- Remove unused dependencies529- Implement code splitting530- Lazy load non-critical code531```bash532# Analyze bundle533npx webpack-bundle-analyzer dist/stats.json534```535536### Problem: Images Causing Layout Shifts537**Symptoms:** High CLS score, content jumping538**Solution:**539- Always specify width and height540- Use aspect-ratio CSS property541- Reserve space with skeleton loaders542```css543img {544 aspect-ratio: 16 / 9;545 width: 100%;546 height: auto;547}548```549550### Problem: Slow Server Response Time551**Symptoms:** High TTFB (Time to First Byte)552**Solution:**553- Implement server-side caching554- Use CDN for static assets555- Optimize database queries556- Consider static site generation (SSG)557```javascript558// Next.js: Static generation559export async function getStaticProps() {560 const data = await fetchData();561 return {562 props: { data },563 revalidate: 60 // Regenerate every 60 seconds564 };565}566```567568## Performance Checklist569570### Images571- [ ] Convert to modern formats (WebP, AVIF)572- [ ] Implement responsive images573- [ ] Add lazy loading574- [ ] Specify dimensions (width/height)575- [ ] Compress images (< 200KB each)576- [ ] Use CDN for delivery577578### JavaScript579- [ ] Bundle size < 200KB (gzipped)580- [ ] Implement code splitting581- [ ] Lazy load non-critical code582- [ ] Remove unused dependencies583- [ ] Minify and compress584- [ ] Use async/defer for scripts585586### CSS587- [ ] Inline critical CSS588- [ ] Defer non-critical CSS589- [ ] Remove unused CSS590- [ ] Minify CSS files591- [ ] Use CSS containment592593### Caching594- [ ] Set cache headers for static assets595- [ ] Implement service worker596- [ ] Use CDN caching597- [ ] Cache API responses598- [ ] Version static assets599600### Core Web Vitals601- [ ] LCP < 2.5s602- [ ] FID < 100ms603- [ ] CLS < 0.1604- [ ] TTFB < 600ms605- [ ] TTI < 3.8s606607## Performance Tools608609### Measurement Tools610- **Lighthouse** - Comprehensive performance audit611- **WebPageTest** - Detailed waterfall analysis612- **Chrome DevTools** - Performance profiling613- **PageSpeed Insights** - Real user metrics614- **Web Vitals Extension** - Monitor Core Web Vitals615616### Analysis Tools617- **webpack-bundle-analyzer** - Visualize bundle composition618- **source-map-explorer** - Analyze bundle size619- **Bundlephobia** - Check package sizes before installing620- **ImageOptim** - Image compression tool621622### Monitoring Tools623- **Google Analytics** - Track Core Web Vitals624- **Sentry** - Performance monitoring625- **New Relic** - Application performance monitoring626- **Datadog** - Real user monitoring627628## Related Skills629630- `@react-best-practices` - React performance patterns631- `@frontend-dev-guidelines` - Frontend development standards632- `@systematic-debugging` - Debug performance issues633- `@senior-architect` - Architecture for performance634635## Additional Resources636637- [Web.dev Performance](https://web.dev/performance/)638- [Core Web Vitals](https://web.dev/vitals/)639- [Lighthouse Documentation](https://developers.google.com/web/tools/lighthouse)640- [MDN Performance Guide](https://developer.mozilla.org/en-US/docs/Web/Performance)641- [Next.js Performance](https://nextjs.org/docs/advanced-features/measuring-performance)642- [Image Optimization Guide](https://web.dev/fast/#optimize-your-images)643644---645646**Pro Tip:** Focus on Core Web Vitals (LCP, FID, CLS) first - they have the biggest impact on user experience and SEO rankings!647
Full transparency — inspect the skill content before installing.