dist/plugins/web-performance-web-performance/skills/web-performance-web-performance/SKILL.md
Bundle optimization, render performance, Core Web Vitals
npx skillsauth add agents-inc/skills web-performance-web-performanceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: Bundle budgets: < 200KB main bundle gzipped. Core Web Vitals: LCP < 2.5s, INP < 200ms, CLS < 0.1. Profile before optimizing -- measure actual bottlenecks, don't guess. Lazy load routes and heavy libraries. Use React Compiler (React 19+) for automatic memoization; manual memo only when profiling proves a bottleneck. Monitor real users with web-vitals library, not just Lighthouse.
<critical_requirements>
(You MUST profile BEFORE optimizing - measure actual bottlenecks with browser DevTools, framework profiler, or Lighthouse)
(You MUST set performance budgets BEFORE building features - bundle size limits and Core Web Vitals targets)
(You MUST use named constants for ALL performance thresholds - no magic numbers like 200 or 2.5)
(You MUST monitor Core Web Vitals in production - track LCP, INP, CLS for real users, not just lab metrics)
(You MUST lazy load route components and heavy libraries - code splitting prevents large initial bundles)
</critical_requirements>
Auto-detection: Core Web Vitals, bundle size optimization, LCP, INP, CLS, lazy loading, code splitting, memoization, React Compiler, performance monitoring, web-vitals library, bundle budget, virtualization, react-window, TanStack Virtual
When to use:
When NOT to use:
Key patterns covered:
Detailed Resources:
Performance is a feature, not an afterthought. Fast applications improve user experience, conversion rates, and SEO rankings. Performance optimization requires measurement before action, budgets before building, and monitoring in production.
Core principles:
Set and enforce bundle size limits to prevent bloat. Main bundle should be < 200KB gzipped for fast downloads on 3G networks.
// constants/bundle-budgets.ts
export const BUNDLE_SIZE_BUDGETS_KB = {
MAIN_BUNDLE_GZIPPED: 200,
VENDOR_BUNDLE_GZIPPED: 150,
ROUTE_BUNDLE_GZIPPED: 100,
TOTAL_INITIAL_LOAD_GZIPPED: 500,
MAIN_CSS_GZIPPED: 50,
CRITICAL_CSS_INLINE: 14, // Fits in first TCP packet
} as const;
Why these limits: 200 KB ≈ 1 second download on 3G, faster Time to Interactive (TTI), better mobile performance
Recommended budgets:
For enforcement examples, see examples/code-splitting.md.
Optimize for Google's Core Web Vitals: LCP < 2.5s, INP < 200ms, CLS < 0.1. These metrics impact SEO and user experience.
// constants/web-vitals.ts
export const CORE_WEB_VITALS_THRESHOLDS = {
LCP_SECONDS: 2.5, // Largest Contentful Paint
INP_MS: 200, // Interaction to Next Paint
CLS_SCORE: 0.1, // Cumulative Layout Shift
FCP_SECONDS: 1.8, // First Contentful Paint
TTI_SECONDS: 3.8, // Time to Interactive
TBT_MS: 300, // Total Blocking Time
TTFB_MS: 800, // Time to First Byte
} as const;
Measures loading performance -- when the largest visible element renders.
How to improve: Optimize images (modern formats, preload hero images), minimize render-blocking resources, use CDN for static assets, SSR or SSG for critical content.
Measures interactivity across ALL user interactions (replaced FID in March 2024). Includes input delay, processing time, and presentation delay.
How to improve: Minimize JavaScript execution time, code split to load less JS upfront, use web workers for heavy computation, break up long tasks (> 50ms) with scheduler.yield() or setTimeout.
Measures visual stability -- prevents unexpected layout shifts.
How to improve: Set explicit image/video dimensions, reserve space for dynamic content (ads, embeds), avoid injecting content above existing content, use font-display: swap with size-adjust.
For detailed examples and monitoring setup, see examples/web-vitals.md.
Lazy load route components and heavy libraries. Code splitting keeps the initial bundle small by loading code on demand.
import { lazy, Suspense } from 'react';
// Route-based splitting - each route is a separate chunk
const Dashboard = lazy(() => import('./pages/dashboard'));
const Reports = lazy(() => import('./pages/reports'));
export function App() {
return (
<Suspense fallback={<PageLoader />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/reports" element={<Reports />} />
</Routes>
</Suspense>
);
}
Why good: Splits bundle by route, loads components on demand, users only download what they navigate to
When to lazy load: Route components, heavy feature modules, modals/dialogs, below-fold content
When NOT to lazy load: Above-fold components, error boundaries, loading states
For tree shaking and bundle enforcement, see examples/code-splitting.md.
Profile before memoizing. React Compiler (v1.0, Oct 2025) auto-memoizes in most cases. Manual memo only when profiling proves a bottleneck.
// Only memoize when profiling shows > 5ms render time
const EXPENSIVE_RENDER_MS = 5;
// ✅ Expensive calculation with large dataset
const sortedRows = useMemo(
() => [...rows].sort((a, b) => compareValues(a[sortColumn], b[sortColumn])),
[rows, sortColumn],
);
// ❌ Trivial calculation - memo overhead exceeds cost
const doubled = useMemo(() => value * 2, [value]);
React Compiler (React 19+): Automatically memoizes components, values, and functions at build time. Manual useMemo/useCallback/React.memo rarely needed. Only add manual memo for: third-party interop, non-pure computations, or when profiling shows the compiler missed an optimization.
For complete memoization patterns, see examples/core.md.
</patterns><red_flags>
High Priority Issues:
import _ from 'lodash') -- bundles unused code, prevents tree shakingMedium Priority Issues:
require()) -- prevents tree shakingGotchas & Edge Cases:
React.memo uses shallow comparison -- deep object props always trigger re-renderuseMemo/useCallback have overhead -- only use for expensive operations (> 5ms)</red_flags>
<critical_reminders>
(You MUST profile BEFORE optimizing - measure actual bottlenecks with browser DevTools, framework profiler, or Lighthouse)
(You MUST set performance budgets BEFORE building features - bundle size limits and Core Web Vitals targets)
(You MUST use named constants for ALL performance thresholds - no magic numbers like 200 or 2.5)
(You MUST monitor Core Web Vitals in production - track LCP, INP, CLS for real users, not just lab metrics)
(You MUST lazy load route components and heavy libraries - code splitting prevents large initial bundles)
Failure to follow these rules will result in slow applications, poor Core Web Vitals, large bundles, and degraded user experience.
</critical_reminders>
development
Material Design component library for Vue 3
development
VitePress 1.x — Vue-powered static site generator for documentation sites, built on Vite
tools
Docusaurus 3.x documentation framework — site configuration, docs/blog plugins, sidebars, versioning, MDX, swizzling, and deployment
development
TanStack Form patterns - useForm, form.Field, validators, arrays, linked fields, createFormHook, type safety