perf-web-optimization
Scannednpx machina-cli add skill tech-leads-club/agent-skills/perf-web-optimization --openclawWeb Performance Optimization
Systematic approach: Measure → Identify → Prioritize → Implement → Verify.
Target Metrics
| Metric | Good | Needs Work | Poor |
|---|---|---|---|
| LCP | < 2.5s | 2.5-4s | > 4s |
| INP | < 200ms | 200-500ms | > 500ms |
| CLS | < 0.1 | 0.1-0.25 | > 0.25 |
| TTFB | < 800ms | 800ms-1.8s | > 1.8s |
Quick Wins
1. Images (usually biggest impact on LCP)
<!-- Hero/LCP image: eager + high priority -->
<img src="/hero.webp" alt="Hero" width="1200" height="600" loading="eager" fetchpriority="high" decoding="async" />
<!-- Below fold: lazy load -->
<img src="/product.webp" alt="Product" width="400" height="300" loading="lazy" decoding="async" />
Always set width and height to prevent CLS.
2. Fonts (common LCP/CLS culprit)
<!-- Preconnect to font origin -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<!-- Non-blocking font load -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter&display=swap"
media="print"
onload="this.media='all'"
/>
3. Third-party Scripts (common INP killer)
<!-- Defer to user interaction -->
<script>
function loadThirdParty() {
// Load analytics, chat widgets, etc.
}
;['scroll', 'click', 'touchstart'].forEach((e) => addEventListener(e, loadThirdParty, { once: true, passive: true }))
setTimeout(loadThirdParty, 5000)
</script>
4. Critical CSS
Inline critical CSS in <head>, defer the rest:
<style>
/* critical styles */
</style>
<link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'" />
Bundle Analysis
# Webpack
npx webpack-bundle-analyzer dist/stats.json
# Vite
npx vite-bundle-visualizer
# Check package size before installing
npx bundlephobia <package-name>
Common heavy packages to replace:
moment(67KB) →date-fns(12KB) ordayjs(2KB)lodash(72KB) → cherry-pick imports or native methods
Code Splitting Patterns
// React lazy
const Chart = lazy(() => import('./Chart'))
// Next.js dynamic
const Admin = dynamic(() => import('./Admin'), { ssr: false })
// Vite/Rollup manual chunks
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom']
}
}
}
}
Caching Headers
# Static assets (immutable hash in filename)
Cache-Control: public, max-age=31536000, immutable
# HTML (revalidate)
Cache-Control: no-cache
# API responses
Cache-Control: private, max-age=0, must-revalidate
Measurement
For running audits, reading reports, and setting budgets, use the perf-lighthouse skill.
Checklist
Images
- Modern formats (WebP/AVIF)
- Responsive
srcset -
width/heightattributes -
loading="lazy"below fold -
fetchpriority="high"on LCP image
JavaScript
- Bundle < 200KB gzipped
- Code splitting by route
- Third-party scripts deferred
- No unused dependencies
CSS
- Critical CSS inlined
- Non-critical CSS deferred
- No unused CSS
Fonts
-
font-display: swap - Preconnect to font origin
- Subset if possible
Detailed Examples
For in-depth optimization patterns, see:
- references/core-web-vitals.md - Fixing LCP, CLS, INP issues
- references/bundle-optimization.md - Reducing JS bundle size
- references/image-optimization.md - Image formats, responsive images, sharp scripts
Source
git clone https://github.com/tech-leads-club/agent-skills/blob/main/packages/skills-catalog/skills/(performance)/perf-web-optimization/SKILL.mdView on GitHub Overview
Perf-web-optimization provides a structured approach to systematically improve web performance by measuring, identifying, prioritizing, implementing, and verifying changes. It focuses on reducing bundle size, optimizing images, improving caching, and enabling lazy loading to boost page speed and Lighthouse scores.
How This Skill Works
Begin with measurement and bundle analysis to identify bottlenecks, then apply quick wins (images, fonts, third-party scripts, and critical CSS). Implement caching strategies and code-splitting to reduce payloads, and verify results with audits conducted by perf-lighthouse. The workflow emphasizes practical, targeted fixes rather than Core Web Vitals-specific or Astro-only optimizations.
When to Use It
- When the site feels slow or bundle sizes are large
- When you need to reduce bundle size and load times
- When layout shifts occur and CLS needs lowering
- When you want to improve Time to Interactive / INP
- When optimizing for Lighthouse scores and overall performance
Quick Start
- Step 1: Measure performance and budgets with perf-lighthouse guidance and a quick bundle analysis
- Step 2: Apply quick wins: optimize images, load fonts non-blocking, defer third-party scripts, and inline critical CSS
- Step 3: Implement caching and code-splitting, then re-run audits to verify improvements
Best Practices
- Prioritize LCP assets by using width/height attributes and proper loading hints (eager for hero images, lazy for below-fold images)
- Inline critical CSS and preload non-critical CSS to speed up first render
- Defer or lazy-load third-party scripts and load them after user interaction
- Analyze bundles to enable code splitting and vendor chunking; replace heavy libraries with lighter alternatives
- Set proper caching headers for static assets and API responses to maximize reuse
Example Use Cases
- Hero image is marked with width/height and loading='eager' with fetchpriority='high' to improve LCP
- Fonts are loaded non-blocking via preconnect and a swap-friendly font-face setup to reduce CLS and render delay
- Analytics and chat widgets load only after user interaction to minimize INP impact
- Critical CSS is inlined in the head while non-critical CSS is preloaded or deferred
- Bundle analysis reveals Moment.js and lodash heavy usage; replace with date-fns/dayjs and selective lodash imports