--- name: "Performance Optimization" description: "Optimize Next.js bundle size with code splitting, tree shaking, lazy loading, and build configuration. Apply when improving performance, reducing bundle size, analyzing dependencies, or optimizing load times." allowed-tools: Read, Write, Edit, Bash version: 1.1.0 compatibility: Claude Opus 4.5, Claude Code v2.x updated: 2026-01-24 --- # Performance Optimization Systematic performance optimization for faster load times and reduced resource consumption. ## Overview This Skill enforces: - Code splitting and lazy loading - Tree shaking unused code - Bundle size analysis - Dynamic imports - Image optimization - Build configuration tuning - Compression strategies - Caching headers Apply when optimizing performance, reducing bundle size, or improving load times. ## Code Splitting ### Route-Based Splitting ```tsx // Next.js automatically splits by route app/ ├── dashboard/page.tsx // bundle-1.js ├── settings/page.tsx // bundle-2.js └── analytics/page.tsx // bundle-3.js // Only loaded when user visits that route ``` ### Component-Level Splitting ```tsx // ✅ GOOD: Lazy load heavy components import dynamic from 'next/dynamic'; const HeavyChart = dynamic(() => import('@/components/Chart'), { loading: () =>
Loading chart...
, ssr: false // Don't render on server }); export default function Dashboard() { return (

Dashboard

{/* Loaded only when page loads */}
); } // ❌ BAD: Import everything upfront import { HeavyChart } from '@/components/Chart'; // Included in main bundle even if user doesn't need it ``` ### Dynamic Imports ```ts // Load module only when needed app.get('/api/reports', async (req, res) => { const { generateReport } = await import('@/lib/report-generator'); const result = await generateReport(); res.json(result); }); // ✅ GOOD: Module loaded only for /api/reports // ❌ BAD: Module loaded at startup const { generateReport } = require('@/lib/report-generator'); ``` ## Tree Shaking ### Configure package.json ```json { "name": "myapp", "sideEffects": false, // No side effects, safe to remove "exports": { ".": "./dist/index.js", "./utils": "./dist/utils.js" } } ``` ### Use Named Exports ```ts // ✅ GOOD: Tree shakeable (named exports) export function usedFunction() { } export function unusedFunction() { } // Only used functions included in bundle import { usedFunction } from './module'; // ❌ BAD: Not tree shakeable (default export) export default { usedFunction, unusedFunction }; // Everything included in bundle import module from './module'; module.usedFunction(); ``` ### Import Only What You Need ```ts // ✅ GOOD: Import specific function import { debounce } from 'lodash-es'; // ❌ BAD: Import entire library import * as _ from 'lodash'; const debounce = _.debounce; // Entire library included ``` ## Bundle Analysis ### Analyze Bundle Size ```bash # Install analyzer npm install -D @next/bundle-analyzer # Configure next.config.js const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true', }); module.exports = withBundleAnalyzer({ // Next.js config }); # Analyze ANALYZE=true npm run build ``` ### Tools for Analysis ```bash # webpack-bundle-analyzer npm install -D webpack-bundle-analyzer # esbuild npm install -D esbuild # Source map explorer npm install -D source-map-explorer npm run source-map-explorer 'dist/**/*.js.map' ``` ## Image Optimization ### Next.js Image Component ```tsx // ✅ GOOD: Optimized images import Image from 'next/image'; export function UserAvatar({ src, alt }) { return ( {alt} ); } // ❌ BAD: Unoptimized {alt} // No lazy loading, no optimization ``` ### Image Formats ```tsx // ✅ GOOD: Modern formats with fallback // ✅ GOOD: WebP with Next.js {alt} ``` ## Build Configuration ### next.config.js Optimization ```js /** @type {import('next').NextConfig} */ const nextConfig = { // Enable SWC minification (faster) swcMinify: true, // Optimize packages optimizePackageImports: [ '@mui/material', '@mui/icons-material', 'lodash-es' ], // Image optimization images: { remotePatterns: [ { protocol: 'https', hostname: 'cdn.example.com' } ], formats: ['image/avif', 'image/webp'], imageSizes: [16, 32, 48, 64, 96, 128, 256], deviceSizes: [640, 750, 828, 1080, 1200, 1920] }, // Compression compress: true, // Generate source maps only in dev productionBrowserSourceMaps: false }; module.exports = nextConfig; ``` ## Lazy Loading Components ### React Suspense ```tsx import { Suspense } from 'react'; async function SlowComponent() { // Simulate slow operation await new Promise(r => setTimeout(r, 3000)); return
Loaded after 3 seconds
; } export default function Page() { return (

Dashboard

{/* Show immediately */}

Quick stats

{/* Lazy load with fallback */} Loading...
}> ); } ``` ### Dynamic Suspense ```tsx import dynamic from 'next/dynamic'; import { Suspense } from 'react'; const LazyChart = dynamic( () => import('@/components/Chart'), { loading: () =>
Loading chart...
, ssr: false } ); export default function Dashboard() { return ( Loading...}> ); } ``` ## Performance Metrics ### Web Vitals ```ts // lib/web-vitals.ts import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'; function sendToAnalytics(metric) { console.log(metric); // Send to analytics service } getCLS(sendToAnalytics); getFID(sendToAnalytics); getFCP(sendToAnalytics); getLCP(sendToAnalytics); getTTFB(sendToAnalytics); ``` ## Caching Strategies ### HTTP Caching Headers ```ts // ✅ GOOD: Cache static assets long-term response.headers.set('Cache-Control', 'public, max-age=31536000, immutable'); // ✅ GOOD: Cache HTML (revalidate frequently) response.headers.set('Cache-Control', 'public, max-age=3600, s-maxage=3600'); // ✅ GOOD: No cache for API responses response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate'); ``` ### Service Worker Caching ```ts // lib/service-worker.ts const CACHE_NAME = 'v1'; const urlsToCache = [ '/', '/offline.html', '/styles/main.css', '/scripts/main.js' ]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { return cache.addAll(urlsToCache); }) ); }); self.addEventListener('fetch', (event) => { if (event.request.method !== 'GET') return; event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request); }) ); }); ``` ## Compression ```ts // ✅ GOOD: Enable compression import compression from 'compression'; app.use(compression()); // Middleware in Next.js export async function middleware(request: NextRequest) { const response = NextResponse.next(); response.headers.set('Content-Encoding', 'gzip'); return response; } ``` ## Anti-Patterns ```ts // ❌ BAD: Import entire library import _ from 'lodash'; _.debounce(fn, 300); // ✅ GOOD: Import specific function import { debounce } from 'lodash-es'; debounce(fn, 300); // ❌ BAD: Large unoptimized image // ✅ GOOD: Optimized with Next.js Image // ❌ BAD: No code splitting import * from './all-components'; // ✅ GOOD: Lazy load const Component = dynamic(() => import('./heavy-component')); // ❌ BAD: No caching response.headers.set('Cache-Control', 'no-cache'); // ✅ GOOD: Cache appropriately response.headers.set('Cache-Control', 'public, max-age=31536000'); ``` ## Verification Before Production - [ ] Bundle size analyzed - [ ] Code splitting enabled for routes - [ ] Heavy components lazy loaded - [ ] Tree shaking configured - [ ] Images optimized (Next.js Image) - [ ] Unused packages removed - [ ] Build optimized (SWC, minification) - [ ] Caching headers set - [ ] Service Worker (if offline support needed) - [ ] Web Vitals monitored ## Integration with Project Standards Enforces performance optimization: - Fast page loads (better UX) - Reduced bandwidth usage - Improved SEO (Core Web Vitals) - Better mobile experience ## Resources - Next.js Performance: https://nextjs.org/learn/foundation/how-nextjs-works/rendering - Bundle Analysis: https://nextjs.org/docs/advanced-features/analyzing-bundles - Web Vitals: https://web.dev/vitals --- **Last Updated:** January 24, 2026 **Compatibility:** Claude Opus 4.5, Claude Code v2.x **Status:** Production Ready > **January 2026 Update:** This skill is compatible with Claude Opus 4.5 and Claude Code v2.x. For complex tasks, use the `effort: high` parameter for thorough analysis.