---
name: web-performance-optimization
description: Comprehensive guide to web performance optimization techniques, Core Web Vitals, and best practices across frameworks
---
# Web Performance Optimization Guide
This skill provides comprehensive knowledge about web performance optimization, Core Web Vitals, and practical techniques for improving website speed and user experience.
## Core Web Vitals
### 1. Largest Contentful Paint (LCP)
**What it measures:** Loading performance - time until the largest content element is visible.
**Good:** < 2.5s | **Needs Improvement:** 2.5s - 4.0s | **Poor:** > 4.0s
**Common causes of poor LCP:**
- Slow server response times
- Render-blocking JavaScript and CSS
- Slow resource load times
- Client-side rendering
**Optimization strategies:**
```html
```
```javascript
// Implement adaptive loading based on network
if (navigator.connection && navigator.connection.effectiveType === '4g') {
// Load high-res images
} else {
// Load lower-res images
}
```
### 2. First Input Delay (FID) / Interaction to Next Paint (INP)
**What it measures:** Interactivity - time from first user interaction to browser response.
**Good (FID):** < 100ms | **Needs Improvement:** 100ms - 300ms | **Poor:** > 300ms
**Good (INP):** < 200ms | **Needs Improvement:** 200ms - 500ms | **Poor:** > 500ms
**Common causes:**
- Heavy JavaScript execution
- Long tasks blocking main thread
- Large bundle sizes
**Optimization strategies:**
```javascript
// Code splitting - load only what's needed
import('./heavy-module.js').then(module => {
module.init();
});
// Use web workers for heavy computation
const worker = new Worker('worker.js');
worker.postMessage({data: largeDataset});
// Debounce expensive operations
const debouncedSearch = debounce((query) => {
performSearch(query);
}, 300);
// Use requestIdleCallback for non-critical work
requestIdleCallback(() => {
analytics.track('page_view');
});
```
### 3. Cumulative Layout Shift (CLS)
**What it measures:** Visual stability - unexpected layout shifts during page load.
**Good:** < 0.1 | **Needs Improvement:** 0.1 - 0.25 | **Poor:** > 0.25
**Common causes:**
- Images without dimensions
- Dynamically injected content
- Web fonts causing FOIT/FOUT
- Ads, embeds, iframes
**Optimization strategies:**
```html
```
## Performance Optimization Techniques
### 1. Resource Optimization
#### Image Optimization
```bash
# Convert to WebP (90% smaller than JPEG)
cwebp input.jpg -q 80 -o output.webp
# Generate responsive images
convert input.jpg -resize 400x output-400w.jpg
convert input.jpg -resize 800x output-800w.jpg
convert input.jpg -resize 1200x output-1200w.jpg
```
```html
```
#### JavaScript Optimization
```javascript
// Tree shaking - import only what you need
import { debounce } from 'lodash-es'; // Good
// import _ from 'lodash'; // Bad - imports everything
// Dynamic imports for route-based code splitting
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
// Minimize third-party scripts
// Use Partytown for offloading to web worker
```
#### CSS Optimization
```html
```
### 2. Network Optimization
#### Compression
```nginx
# Enable gzip/brotli compression (nginx)
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
# Brotli (better compression)
brotli on;
brotli_types text/plain text/css application/json application/javascript;
```
#### HTTP/2 & HTTP/3
```nginx
# Enable HTTP/2
listen 443 ssl http2;
# Enable HTTP/3 (QUIC)
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';
```
#### Caching Strategy
```javascript
// Service Worker caching
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v1').then((cache) => {
return cache.addAll([
'/',
'/styles.css',
'/script.js',
'/logo.svg'
]);
})
);
});
// Cache-first strategy for static assets
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});
```
```nginx
# HTTP caching headers
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
```
### 3. Rendering Optimization
#### Critical Rendering Path
```html
```
#### Server-Side Rendering (SSR) vs Client-Side Rendering (CSR)
```javascript
// Next.js - Hybrid approach
export async function getServerSideProps() {
// Fetch data on server
const data = await fetch('https://api.example.com/data');
return { props: { data } };
}
// Static generation for faster TTFB
export async function getStaticProps() {
const data = await fetch('https://api.example.com/data');
return {
props: { data },
revalidate: 60 // ISR - revalidate every 60s
};
}
```
### 4. Framework-Specific Optimizations
#### React
```javascript
// Lazy load components
const HeavyComponent = lazy(() => import('./HeavyComponent'));
// Memoization
const MemoizedComponent = React.memo(({ data }) => {
return {data}
;
});
// useMemo for expensive computations
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b);
}, [a, b]);
// useCallback for function references
const handleClick = useCallback(() => {
doSomething(a);
}, [a]);
// Virtualization for long lists
import { FixedSizeList } from 'react-window';
{Row}
```
#### Vue
```javascript
// Async components
const AsyncComponent = defineAsyncComponent(() =>
import('./HeavyComponent.vue')
);
// Keep-alive for component caching
// v-once for static content
{{ staticContent }}
// Virtual scrolling
import { RecycleScroller } from 'vue-virtual-scroller';
```
#### Angular
```typescript
// Lazy loading routes
const routes: Routes = [
{
path: 'feature',
loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
}
];
// OnPush change detection
@Component({
selector: 'app-component',
changeDetection: ChangeDetectionStrategy.OnPush
})
// TrackBy for *ngFor
{{ item.name }}
trackByFn(index, item) {
return item.id;
}
```
## Database & Backend Optimization
### N+1 Query Problem
```javascript
// Bad - N+1 queries
const users = await User.findAll();
for (const user of users) {
const posts = await Post.findAll({ where: { userId: user.id } });
}
// Good - Single query with join
const users = await User.findAll({
include: [{ model: Post }]
});
```
### Caching Strategies
```javascript
// Redis caching
const cached = await redis.get(`user:${id}`);
if (cached) {
return JSON.parse(cached);
}
const user = await db.users.findById(id);
await redis.set(`user:${id}`, JSON.stringify(user), 'EX', 3600);
return user;
// Memoization
const memoize = (fn) => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
};
};
```
### Database Indexing
```sql
-- Create indexes for frequently queried columns
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_posts_user_id ON posts(user_id);
-- Composite indexes for multi-column queries
CREATE INDEX idx_posts_user_date ON posts(user_id, created_at);
-- Analyze query performance
EXPLAIN ANALYZE SELECT * FROM posts WHERE user_id = 123;
```
## Performance Monitoring
### Real User Monitoring (RUM)
```javascript
// Web Vitals API
import {getCLS, getFID, getFCP, getLCP, getTTFB} from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getFCP(console.log);
getLCP(console.log);
getTTFB(console.log);
// Send to analytics
function sendToAnalytics({name, value, id}) {
analytics.track('web-vital', {
metric: name,
value: Math.round(value),
id
});
}
getCLS(sendToAnalytics);
getLCP(sendToAnalytics);
```
### Performance Observer API
```javascript
// Observe long tasks
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 50) {
console.warn('Long task detected:', entry);
}
}
});
observer.observe({entryTypes: ['longtask']});
// Monitor resource timing
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('Resource:', entry.name, 'Duration:', entry.duration);
}
}).observe({entryTypes: ['resource']});
```
## Common Performance Anti-Patterns
### 1. Blocking the Main Thread
```javascript
// Bad - blocks UI
for (let i = 0; i < 1000000; i++) {
// Heavy computation
}
// Good - chunk work
function processInChunks(data, chunkSize = 100) {
let index = 0;
function processChunk() {
const chunk = data.slice(index, index + chunkSize);
// Process chunk
index += chunkSize;
if (index < data.length) {
requestIdleCallback(processChunk);
}
}
processChunk();
}
```
### 2. Memory Leaks
```javascript
// Bad - creates memory leak
class Component {
constructor() {
setInterval(() => {
this.updateState();
}, 1000);
}
}
// Good - cleanup
class Component {
constructor() {
this.interval = setInterval(() => {
this.updateState();
}, 1000);
}
destroy() {
clearInterval(this.interval);
}
}
```
### 3. Excessive Re-renders
```javascript
// Bad - re-renders on every parent update
function Child({ items }) {
return items.map(item => {item.name}
);
}
// Good - memoized
const Child = React.memo(function Child({ items }) {
return items.map(item => {item.name}
);
}, (prevProps, nextProps) => {
return prevProps.items === nextProps.items;
});
```
## Performance Budget
Set and enforce performance budgets:
```json
{
"budgets": [
{
"resourceSizes": [
{"resourceType": "script", "budget": 300},
{"resourceType": "image", "budget": 500},
{"resourceType": "stylesheet", "budget": 50}
],
"resourceCounts": [
{"resourceType": "third-party", "budget": 10}
],
"timings": [
{"metric": "interactive", "budget": 3000},
{"metric": "first-contentful-paint", "budget": 1500}
]
}
]
}
```
## Testing Tools
- **Lighthouse**: Automated audits
- **WebPageTest**: Real device testing
- **Chrome DevTools**: Performance profiling
- **bundlephobia.com**: Check package sizes
- **web.dev**: Best practices and guides
## Key Takeaways
1. **Measure first**: Use Lighthouse, Web Vitals, RUM
2. **Optimize critical path**: Inline critical CSS, defer JS
3. **Reduce bundle size**: Code splitting, tree shaking
4. **Optimize images**: WebP, lazy loading, responsive images
5. **Cache effectively**: Service workers, HTTP caching
6. **Minimize main thread work**: Web workers, chunking
7. **Monitor continuously**: Real user monitoring
8. **Set budgets**: Enforce performance standards