Why Performance Is a Feature
A 1-second delay in page load reduces conversions by 7%. For a SaaS product, that means fewer signups, more churn, and lower revenue.
Performance isn't a nice-to-have — it's a competitive advantage. Users won't tell you your app is slow. They'll just stop using it.
Here's how to make your React app fast, with techniques ordered by impact.
Code Splitting and Lazy Loading
This is the single highest-impact optimization for most React apps.
The problem: By default, your entire app is bundled into one JavaScript file. Users download everything — including pages they never visit.
The fix: Use React.lazy() and Suspense to split your app into chunks.
```tsx const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings'));
This means the Settings page code only loads when a user actually navigates to /settings. For a typical SaaS with 10+ pages, this reduces initial load by 40-60%.
Memoization: React.memo, useMemo, useCallback
React re-renders components whenever their parent re-renders. In a complex SaaS dashboard, this means hundreds of unnecessary re-renders per interaction.
React.memo: Wrap components that receive the same props frequently. It tells React to skip re-rendering if props haven't changed.
useMemo: Cache expensive calculations. If you're filtering a list of 1,000 items, memoize the filtered result.
useCallback: Cache function references. Without it, every render creates a new function, which triggers re-renders in child components.
Important: Don't memoize everything. Memoization has its own cost (memory, comparison checks). Only use it when you have a measurable performance problem. Profile first with React DevTools, then optimize.
Bundle Analysis
You can't optimize what you can't measure. Install a bundle analyzer to see exactly what's in your JavaScript bundle.
For Vite: Use rollup-plugin-visualizer For webpack: Use webpack-bundle-analyzer
Common findings: - A date library (moment.js) taking up 300KB → Replace with date-fns (50KB) or dayjs (7KB) - An icon library importing everything → Use tree-shaking imports - Unused dependencies → Remove them - Large images bundled in JS → Move to public folder with lazy loading
We reduced one client's bundle from 1.8MB to 420KB just by replacing three dependencies and adding proper tree-shaking. Their Lighthouse performance score went from 38 to 91.
Image and Asset Optimization
Images are often the largest assets on a page.
Use WebP or AVIF format. They're 30-50% smaller than PNG/JPEG with the same quality.
Lazy load below-fold images. Use the loading="lazy" attribute or an intersection observer.
Set explicit dimensions. This prevents layout shift (CLS) which hurts both UX and SEO.
Use responsive images. Serve different sizes based on screen width with srcSet.
Optimize SVGs. Run them through SVGO to remove unnecessary metadata. An optimized SVG is often under 1KB.
Measuring Success: Lighthouse Scores
Run Lighthouse in Chrome DevTools → Performance tab. Here's what to aim for:
- Performance: 90+ (most SaaS apps score 40-60 before optimization) - First Contentful Paint: Under 1.8s - Largest Contentful Paint: Under 2.5s - Total Blocking Time: Under 200ms - Cumulative Layout Shift: Under 0.1
Test on a throttled connection (4G, not your fiber). Test on a real phone, not just desktop. Your users aren't all on MacBook Pros.
Make performance a habit. Run Lighthouse after every major feature. Set up performance budgets in your CI/CD pipeline. A fast app isn't a one-time achievement — it's an ongoing practice.
Rajhussain
Written by Rajhussain, founder of Hykvra Studio. Full-stack developer and technical SEO analyst with 5+ years of experience building and launching SaaS products. Based in Hyderabad, India. He's personally built and shipped CheckSEO.dev, AI Video Creator, and 10+ client MVPs.