Most React performance problems are not React problems. They are network, bundle size, or layout problems. Profile first. Optimize second. Guess never.
Profiling Your Application
Use React DevTools Profiler and Lighthouse. Measure real-world performance, not local performance:
// Enable React Profiler
import { Profiler } from "react";
function onRenderCallback(
id: string,
phase: "mount" | "update",
actualDuration: number
) {
console.log(`${id} (${phase}) took ${actualDuration}ms`);
}
export default function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<YourApp />
</Profiler>
);
}Code Splitting and Lazy Loading
Split your bundle. Load non-critical code later. Most applications can cut initial bundle size by 50%:
// Dynamic import for page components
import dynamic from "next/dynamic";
const AdminPanel = dynamic(
() => import("@/components/AdminPanel"),
{ loading: () => <div>Loading...</div> }
);
export default function Dashboard() {
return (
<>
<Header />
<AdminPanel /> {/* Only loads when needed */}
</>
);
}Memoization Patterns
Use memoization strategically. Avoid premature optimization:
// Memoize expensive computations
import { useMemo } from "react";
function ExpensiveList({ items }: { items: Item[] }) {
const sortedItems = useMemo(
() => items.sort((a, b) => b.date - a.date),
[items] // Only recompute when items changes
);
return (
<ul>
{sortedItems.map((item) => (
<ListItem key={item.id} item={item} />
))}
</ul>
);
}
// Memoize callbacks passed to children
export function Parent() {
const handleClick = useCallback(() => {
console.log("clicked");
}, []);
return <Child onClick={handleClick} />;
}Optimize Images
Images are usually the bottleneck. Optimize aggressively:
import Image from "next/image";
export function OptimizedImage() {
return (
<Image
src="/image.jpg"
alt="Description"
width={800}
height={600}
placeholder="blur" // Show blurred placeholder while loading
quality={75} // Reduce quality for web (75-80 is usually fine)
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px"
/>
);
}Network Is Usually the Bottleneck
JavaScript optimizations usually don't matter if your API calls take 5 seconds. Fix the network first:
- API response time: Profile your backend. Slow queries? Slow APIs? Fix that first.
- Bundle size: Check your initial JavaScript. Over 100KB? Code split aggressively.
- Image optimization: Serve WebP. Resize for device. Use CDN.
- Caching: Cache API responses. Cache static assets for years.