How I Optimized React App Performance by 40% at Enterprise Scale

Anup Singh
Anup SinghSenior Frontend Developer
5 min read
Listen to Article
7 min
0:007:00
Developer working on laptop with code on screen optimizing web application performance

The Problem: A Sluggish Enterprise Application

When I took over as frontend lead on a major enterprise web platform, the application was suffering from severe performance issues. Users were experiencing:

  • Time to Interactive (TTI): 8.2 seconds on average
  • First Contentful Paint (FCP): 3.8 seconds
  • Largest Contentful Paint (LCP): 5.6 seconds
  • Bundle size: 2.4MB (uncompressed JavaScript)
The client was losing users. Analytics showed a 35% bounce rate increase over 3 months. Something had to change — fast.

Performance Snapshot

Before Optimization

8.2s
Time to Interactive
3.8s
First Contentful Paint
5.6s
Largest Contentful Paint
2.4MB
Bundle Size

In this article, I'll walk you through the exact optimization strategy I implemented that reduced TTI by 40%, brought LCP under 2.5 seconds, and cut the bundle size by 60%.


My 6-Step Optimization Process

01
Profile & Identify
2 days of deep profiling with React DevTools + Lighthouse
02
Fix Re-renders
Granular selectors + React.memo eliminated 60% of wasted renders
03
Code Splitting
Route + component-level splitting reduced bundle by 63%
04
Image Optimization
WebP + lazy loading + responsive sizes cut images by 82%
05
Script Management
Defer + lazy strategies saved 800ms render-blocking time
06
Caching & Prefetch
Service worker + route prefetching for instant navigation


Step 1: Profiling — Finding the Real Bottlenecks

Before writing a single line of optimized code, I spent two full days profiling. This is the most important step — never optimize blindly.

Tools I Used:

  • React DevTools Profiler — to identify unnecessary re-renders
  • Chrome DevTools Performance tab — to find long tasks blocking the main thread
  • Lighthouse CI — for automated performance scoring in our pipeline
  • Bundle Analyzer — to visualize what's actually in the bundle

What I Found:

IssueImpactPriority
Entire Redux store re-rendering on every action45% of unnecessary rendersCritical
No code splitting — single monolithic bundle2.4MB initial loadCritical
Unoptimized images (PNG, no lazy loading)1.8MB additional payloadHigh
Synchronous third-party scripts800ms render blockingHigh
Inline styles causing layout thrashingPoor CLS scoreMedium

Pro Tip: Never optimize blindly. Always profile first. The bottlenecks are rarely where you think they are.


Step 2: Eliminating Unnecessary Re-renders

This was the single biggest win. The Redux store was structured poorly, causing the entire component tree to re-render on every state change.

Before
  • Selecting entire store object
  • Every component re-renders on any change
  • No memoization anywhere
  • 500+ item lists rendered directly in DOM
After
  • Granular selectors with createSelector
  • Only affected components re-render
  • React.memo on 23 expensive components
  • Virtualized lists with react-window (~20 DOM nodes)

The techniques in detail:

  1. Granular Redux Selectors — Instead of selecting the entire store, we created pinpoint selectors using createSelector that only trigger re-renders when the specific piece of data changes.
  1. React.memo on 23 components — Wrapped expensive components that were pure but re-rendering due to parent updates.
  1. useMemo for computed values — Identified 15 places where expensive filtering/sorting ran on every render.
  1. Virtualization — Replaced a 500+ item product list with react-window, reducing DOM nodes from 2000+ to ~20 visible.

Result: 60% reduction in unnecessary re-renders


Step 3: Aggressive Code Splitting

The monolithic 2.4MB bundle was killing initial load time. I split it at two levels:

Bundle Reduction

From 2.4MB to 890KB

Route-Level Splitting -45%
Lazy-loaded each route with React.lazy + Suspense
Component-Level Splitting -12%
Heavy chart library loaded only on analytics page
Vendor Chunk Optimization -6%
Separated vendor chunks for better caching

Result: Bundle reduced from 2.4MB to 890KB initial load (63% reduction)


Step 4: Image Optimization

Images accounted for 1.8MB of the page weight. Three changes made all the difference:

  1. WebP format — 40% smaller than PNG with same quality
  2. Responsive sizes — Serve device-appropriate images (640px for mobile, 1920px for desktop)
  3. Smart loading — Hero image loads eager with high priority, everything else lazy loads

Result: Image payload reduced from 1.8MB to 320KB (82% reduction)


Step 5: Third-Party Script Management

Third-party scripts were blocking rendering for 800ms. The fix was simple — proper loading strategies:

ScriptStrategySavings
Google AnalyticsLoad after first interaction200ms
Chat WidgetLoad only when user scrolls350ms
Marketing PixelsOffload to web worker250ms

Result: 800ms saved in render-blocking time


Step 6: Caching & Prefetching

The final layer — making repeat visits and navigation instant:

  • API Response Caching — SessionStorage cache with 5-minute TTL for frequently accessed data
  • Route Prefetching — Prefetch likely next pages on hover
  • Static Asset Caching — Aggressive service worker caching for CSS, JS, and images

The Final Results

Results Achieved

Before vs After Optimization

TTI
8.2s
4.9s
-40%
LCP
5.6s
2.3s
-59%
Size
2.4MB
890KB
-63%
Lighthouse: 42 → 91


Key Takeaways

  1. Always profile before optimizing — Don't guess where the bottlenecks are
  2. Re-renders are the silent killer — Use React DevTools Profiler religiously
  3. Code splitting is non-negotiable — No user should download code they won't use
  4. Images are usually the biggest payload — WebP + lazy loading = instant wins
  5. Third-party scripts add up — Audit and defer everything that's not critical
  6. Measure continuously — Set up Lighthouse CI to catch regressions early

Tools and Resources


Have questions about React performance optimization? Feel free to reach out on LinkedIn or email me.

Tags:ReactPerformanceWeb VitalsOptimizationMemoizationCode Splitting
Anup Singh

Written by

Anup Singh

Senior Software Engineer & Frontend Developer

Building high-performance web applications with React, Next.js, and JavaScript for 9.5+ years at enterprise scale. Leading dev teams and mentoring engineers in Bangalore, India.