---
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 (
);
}
// ❌ BAD: Unoptimized
// No lazy loading, no optimization
```
### Image Formats
```tsx
// ✅ GOOD: Modern formats with fallback
// ✅ GOOD: WebP with Next.js
```
## 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.