optimize.md

  1Performance is a feature. Identify the actual bottleneck for THIS interface, fix it, then measure. Don't optimize what isn't slow.
  2
  3## Assess Performance Issues
  4
  5Understand current performance and identify problems:
  6
  71. **Measure current state**:
  8   - **Core Web Vitals**: LCP, FID/INP, CLS scores
  9   - **Load time**: Time to interactive, first contentful paint
 10   - **Bundle size**: JavaScript, CSS, image sizes
 11   - **Runtime performance**: Frame rate, memory usage, CPU usage
 12   - **Network**: Request count, payload sizes, waterfall
 13
 142. **Identify bottlenecks**:
 15   - What's slow? (Initial load? Interactions? Animations?)
 16   - What's causing it? (Large images? Expensive JavaScript? Layout thrashing?)
 17   - How bad is it? (Perceivable? Annoying? Blocking?)
 18   - Who's affected? (All users? Mobile only? Slow connections?)
 19
 20**CRITICAL**: Measure before and after. Premature optimization wastes time. Optimize what actually matters.
 21
 22## Optimization Strategy
 23
 24Create systematic improvement plan:
 25
 26### Loading Performance
 27
 28**Optimize Images**:
 29- Use modern formats (WebP, AVIF)
 30- Proper sizing (don't load 3000px image for 300px display)
 31- Lazy loading for below-fold images
 32- Responsive images (`srcset`, `picture` element)
 33- Compress images (80-85% quality is usually imperceptible)
 34- Use CDN for faster delivery
 35
 36```html
 37<img 
 38  src="hero.webp"
 39  srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
 40  sizes="(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px"
 41  loading="lazy"
 42  alt="Hero image"
 43/>
 44```
 45
 46**Reduce JavaScript Bundle**:
 47- Code splitting (route-based, component-based)
 48- Tree shaking (remove unused code)
 49- Remove unused dependencies
 50- Lazy load non-critical code
 51- Use dynamic imports for large components
 52
 53```javascript
 54// Lazy load heavy component
 55const HeavyChart = lazy(() => import('./HeavyChart'));
 56```
 57
 58**Optimize CSS**:
 59- Remove unused CSS
 60- Critical CSS inline, rest async
 61- Minimize CSS files
 62- Use CSS containment for independent regions
 63
 64**Optimize Fonts**:
 65- Use `font-display: swap` or `optional`
 66- Subset fonts (only characters you need)
 67- Preload critical fonts
 68- Use system fonts when appropriate
 69- Limit font weights loaded
 70
 71```css
 72@font-face {
 73  font-family: 'CustomFont';
 74  src: url('/fonts/custom.woff2') format('woff2');
 75  font-display: swap; /* Show fallback immediately */
 76  unicode-range: U+0020-007F; /* Basic Latin only */
 77}
 78```
 79
 80**Optimize Loading Strategy**:
 81- Critical resources first (async/defer non-critical)
 82- Preload critical assets
 83- Prefetch likely next pages
 84- Service worker for offline/caching
 85- HTTP/2 or HTTP/3 for multiplexing
 86
 87### Rendering Performance
 88
 89**Avoid Layout Thrashing**:
 90```javascript
 91// ❌ Bad: Alternating reads and writes (causes reflows)
 92elements.forEach(el => {
 93  const height = el.offsetHeight; // Read (forces layout)
 94  el.style.height = height * 2; // Write
 95});
 96
 97// ✅ Good: Batch reads, then batch writes
 98const heights = elements.map(el => el.offsetHeight); // All reads
 99elements.forEach((el, i) => {
100  el.style.height = heights[i] * 2; // All writes
101});
102```
103
104**Optimize Rendering**:
105- Use CSS `contain` property for independent regions
106- Minimize DOM depth (flatter is faster)
107- Reduce DOM size (fewer elements)
108- Use `content-visibility: auto` for long lists
109- Virtual scrolling for very long lists (react-window, react-virtualized)
110
111**Reduce Paint & Composite**:
112- Use `transform` and `opacity` for reliable movement, but allow blur, filters, masks, clip paths, shadows, and color shifts when they create meaningful polish
113- Avoid casual animation of layout-driving properties (`width`, `height`, `top`, `left`, margins)
114- Use `will-change` sparingly for known expensive operations
115- Bound expensive paint areas for blur/filter/shadow effects (smaller and isolated is faster)
116
117### Animation Performance
118
119**GPU Acceleration**:
120```css
121/* ✅ GPU-accelerated (fast) */
122.animated {
123  transform: translateX(100px);
124  opacity: 0.5;
125}
126
127/* ❌ CPU-bound (slow) */
128.animated {
129  left: 100px;
130  width: 300px;
131}
132```
133
134**Smooth 60fps**:
135- Target 16ms per frame (60fps)
136- Use `requestAnimationFrame` for JS animations
137- Debounce/throttle scroll handlers
138- Use CSS animations when possible
139- Avoid long-running JavaScript during animations
140
141**Intersection Observer**:
142```javascript
143// Efficiently detect when elements enter viewport
144const observer = new IntersectionObserver((entries) => {
145  entries.forEach(entry => {
146    if (entry.isIntersecting) {
147      // Element is visible, lazy load or animate
148    }
149  });
150});
151```
152
153### React/Framework Optimization
154
155**React-specific**:
156- Use `memo()` for expensive components
157- `useMemo()` and `useCallback()` for expensive computations
158- Virtualize long lists
159- Code split routes
160- Avoid inline function creation in render
161- Use React DevTools Profiler
162
163**Framework-agnostic**:
164- Minimize re-renders
165- Debounce expensive operations
166- Memoize computed values
167- Lazy load routes and components
168
169### Network Optimization
170
171**Reduce Requests**:
172- Combine small files
173- Use SVG sprites for icons
174- Inline small critical assets
175- Remove unused third-party scripts
176
177**Optimize APIs**:
178- Use pagination (don't load everything)
179- GraphQL to request only needed fields
180- Response compression (gzip, brotli)
181- HTTP caching headers
182- CDN for static assets
183
184**Optimize for Slow Connections**:
185- Adaptive loading based on connection (navigator.connection)
186- Optimistic UI updates
187- Request prioritization
188- Progressive enhancement
189
190## Core Web Vitals Optimization
191
192### Largest Contentful Paint (LCP < 2.5s)
193- Optimize hero images
194- Inline critical CSS
195- Preload key resources
196- Use CDN
197- Server-side rendering
198
199### First Input Delay (FID < 100ms) / INP (< 200ms)
200- Break up long tasks
201- Defer non-critical JavaScript
202- Use web workers for heavy computation
203- Reduce JavaScript execution time
204
205### Cumulative Layout Shift (CLS < 0.1)
206- Set dimensions on images and videos
207- Don't inject content above existing content
208- Use `aspect-ratio` CSS property
209- Reserve space for ads/embeds
210- Avoid animations that cause layout shifts
211
212```css
213/* Reserve space for image */
214.image-container {
215  aspect-ratio: 16 / 9;
216}
217```
218
219## Performance Monitoring
220
221**Tools to use**:
222- Chrome DevTools (Lighthouse, Performance panel)
223- WebPageTest
224- Core Web Vitals (Chrome UX Report)
225- Bundle analyzers (webpack-bundle-analyzer)
226- Performance monitoring (Sentry, DataDog, New Relic)
227
228**Key metrics**:
229- LCP, FID/INP, CLS (Core Web Vitals)
230- Time to Interactive (TTI)
231- First Contentful Paint (FCP)
232- Total Blocking Time (TBT)
233- Bundle size
234- Request count
235
236**IMPORTANT**: Measure on real devices with real network conditions. Desktop Chrome with fast connection isn't representative.
237
238**NEVER**:
239- Optimize without measuring (premature optimization)
240- Sacrifice accessibility for performance
241- Break functionality while optimizing
242- Use `will-change` everywhere (creates new layers, uses memory)
243- Lazy load above-fold content
244- Optimize micro-optimizations while ignoring major issues (optimize the biggest bottleneck first)
245- Forget about mobile performance (often slower devices, slower connections)
246
247## Verify Improvements
248
249Test that optimizations worked:
250
251- **Before/after metrics**: Compare Lighthouse scores
252- **Real user monitoring**: Track improvements for real users
253- **Different devices**: Test on low-end Android, not just flagship iPhone
254- **Slow connections**: Throttle to 3G, test experience
255- **No regressions**: Ensure functionality still works
256- **User perception**: Does it *feel* faster?
257
258When the user-facing numbers move, hand off to `/impeccable polish` for the final pass.