A React app with a 5MB bundle size and 15-second load time — this was the real problem I faced. Here's the optimization strategy that brought load time down to 1 second.
Initial Audit
Using Lighthouse and Webpack Bundle Analyzer, I found:
- Bundle size: 5.2 MB (uncompressed)
- Largest Contentful Paint (LCP): 12.4s
- First Input Delay (FID): 350ms
- Render-blocking resources: 18 files
Optimization Strategy
1. Code Splitting & Lazy Loading
// Before — all components loaded at once
import Dashboard from './Dashboard';
import Analytics from './Analytics';
import Settings from './Settings';
// After — lazy loading per route
const Dashboard = React.lazy(() => import('./Dashboard'));
const Analytics = React.lazy(() => import('./Analytics'));
const Settings = React.lazy(() => import('./Settings'));
2. Image Optimization
- WebP format with fallback
- Responsive images with srcset
- Lazy loading for below-fold images
3. Caching Strategy
- Service Worker with Workbox
- API response caching in IndexedDB
- Static asset hashing for long-term caching
4. Bundle Analysis & Tree Shaking
- Remove unused dependencies
- Replace heavy libraries with lighter alternatives
- Dynamic imports for large libraries (charts, PDF generation)
Final Results
| Metric | Before | After |
|---|---|---|
| Bundle Size | 5.2 MB | 890 KB |
| LCP | 12.4s | 1.2s |
| FID | 350ms | 45ms |
| Lighthouse Score | 35 | 94 |
Performance optimization is never a one-time job — it's an ongoing process that needs continuous monitoring.