Perceived Speed vs Actual Speed
A page that loads in 2 seconds with a nice skeleton feels faster than one that loads in 1.5 seconds with a blank screen. Performance isn't just about milliseconds. It's about how fast things feel. Design engineers can make a huge impact here because we control what users see while they wait.
Show Something Immediately
The number one rule: never show a blank screen. Show the layout with skeleton placeholders while data loads.
Lazy Load What's Not Visible
Optimize Re-Renders
Unnecessary re-renders are the most common performance killer in React apps:
Animations That Don't Stutter
- Only animate
transformandopacity. These use the GPU. - Never animate
width,height,margin, orpadding. They trigger layout. - Use
will-change: transformsparingly for elements that animate often. - Test on slow devices. Your MacBook Pro hides performance problems.
Bundle Size Matters
Big bundles mean slow first loads. A few things that help:
- Import icons individually:
import { Search } from 'lucide-react'not the whole library - Use dynamic imports for heavy components (charts, editors, maps)
- Check your bundle with
@next/bundle-analyzerregularly - Tree-shake CSS - Tailwind does this automatically in production
Optimistic Updates
Don't wait for the server to respond. Show the result immediately and fix it if the request fails:
The Short Version
- Show skeletons immediately. Never show blank screens.
- Lazy load heavy components and images
- Memoize expensive components or move state closer to where it's used
- Only animate transform and opacity for smooth 60fps
- Watch your bundle size. Import things individually.
- Use optimistic updates for instant-feeling interactions
- Test on slow devices and throttled networks