Optimizing React Performance: From 3s to 300ms
The Problem
Our dashboard was taking 3 seconds to become interactive. Users were bouncing. We needed to fix it fast.
Here's the systematic approach we took to cut load time by 90%.
Step 1: Measure First
Before optimizing anything, we profiled with React DevTools and Lighthouse:
npx lighthouse https://app.example.com --viewThe results showed three main bottlenecks: 1. A 2MB JavaScript bundle 2. 500+ component re-renders on initial load 3. A 200-row table rendering all rows at once
Step 2: Code Splitting
We lazy-loaded every route and heavy component:
const AdminDashboard = lazy(() => import("./admin/dashboard"))
const AnalyticsChart = lazy(() => import("./charts/analytics"))Tip
Don't just code-split routes — split heavy components within routes too. A chart library doesn't need to load until the user scrolls to it.
Step 3: Virtualization
For our 200-row table, we switched to virtual rendering:
function VirtualTable({ items }: { items: Item[] }) { const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 48, }) // Only renders visible rows } ```
Step 4: Strategic Memoization
Not everything should be memoized. We focused on: - Components that receive object/array props - Components in frequently-updating contexts - Expensive computed values
Results
| Metric | Before | After |
|---|---|---|
| TTI | 3.2s | 0.3s |
| Bundle size | 2.1MB | 420KB |
| Re-renders | 500+ | 45 |
| Lighthouse | 34 | 96 |
admin
Senior frontend engineer and tech writer. Passionate about React, TypeScript, and building great developer experiences. Previously at Vercel and Stripe.
Comments (1)
Those before/after metrics are impressive! Did you also try React Server Components for the initial load optimization?
Related Posts
Building a Design System with Tailwind CSS v4 and React
Learn how to create a scalable, token-based design system using Tailwind CSS v4's new CSS-first configuration and React component patterns.
The Complete Guide to Next.js 16 App Router
Everything you need to know about Next.js 16's App Router — from layouts and loading states to parallel routes and intercepting routes.
Mastering TypeScript Generics: Real-World Patterns
Move beyond basic generics with practical patterns for type-safe APIs, component props, and utility types that you'll use every day.