Code Splitting & Performance
Master React performance optimisation — from bundle splitting to render optimisation. Learn the strategies senior engineers use to keep large React applications fast.
Last reviewed: January 2025
🔍 What Is It?
React performance optimisation covers two areas:
1. Bundle performance (load time):
- →Code splitting — split the bundle into chunks that load on demand
- →Tree shaking — remove unused code
- →Lazy loading — defer non-critical code
2. Render performance (runtime):
- →React.memo — prevent unnecessary component re-renders
- →useMemo — prevent expensive recalculations
- →useCallback — stable function references for memoised children
- →Virtualisation — render only visible list items (react-window, TanStack Virtual)
- →Concurrent features — React 18 useTransition, useDeferredValue
🎯 Why Do We Need It?
Performance directly impacts business metrics:
- →1 second delay in page load = 7% reduction in conversions (Amazon study)
- →Core Web Vitals (LCP, FID, CLS) affect Google search ranking
- →Slow UIs increase user frustration and support tickets
- →Large bundles are painful on mobile data connections
In enterprise apps, performance problems compound: a slow dashboard that re-renders 50 components on every keystroke becomes unusable at scale.
🏗️ What Happens in Real Projects?
In a real insurance claims dashboard:
- →Virtualise the claims list (potentially thousands of rows) with react-window
- →Lazy load the PDF viewer, rich text editor, and chart library
- →Debounce search input to reduce API calls
- →useTransition to keep the UI responsive while filtering a large list
- →Memoize the claims table rows to prevent re-renders when selecting a row
⚙️ How It Works
React 18 Concurrent Features:
useTransition — marks a state update as non-urgent. React can interrupt it to handle urgent updates (user input stays responsive):
const [isPending, startTransition] = useTransition();
startTransition(() => setFilter(newFilter)); // non-urgentuseDeferredValue — defers updating a value until the browser is idle:
const deferredQuery = useDeferredValue(searchQuery);
// deferredQuery lags behind searchQuery — used for expensive renderingVirtualisation:
Instead of rendering 10,000 list items (most off-screen), render only the ~20 visible ones. As the user scrolls, swap items in and out. Libraries: react-window, TanStack Virtual.
💻 Example
Performance Patterns in Production — useTransition for responsive filtering and virtualised lists.
🤔 Common Confusions
❓ How do I know if my app has a performance problem?
Use the React DevTools Profiler. Record an interaction, then look for components with long render times (shown in red/orange). Also use Chrome DevTools Performance tab to identify long tasks. Never optimise based on guessing — always measure first.
❓ When should I use useTransition vs useDeferredValue?
useTransition: you control the state update (you call setState). useDeferredValue: you receive a value as a prop and want to defer its use in expensive rendering. useTransition is more common. useDeferredValue is useful when you cannot control when the value changes.
🚨 Common Production Issues
**Rendering 10,000+ items** — Always virtualise large lists. Rendering 10,000 DOM nodes is the single most common React performance problem in enterprise apps.
**Expensive computation on every render** — Sorting/filtering large datasets without useMemo runs on every render including unrelated state changes.
**Large initial bundle** — Not code-splitting at the route level results in a multi-MB initial download. Always lazy load page-level components.
**Waterfall API calls** — Fetching data sequentially (each fetch starts after the previous completes) when they could be parallel. Use Promise.all or React Query's parallel queries.
✅ Best Practices
Measure first with React DevTools Profiler and Chrome Performance tab
Virtualise any list with more than 100 items
Lazy load all page-level route components
Use useTransition for expensive state updates triggered by user input
Avoid rendering large trees on every keystroke — debounce or defer
Use React Query for server state — it handles caching and deduplication automatically
Analyse bundle size with vite-bundle-visualizer or webpack-bundle-analyzer
🏛️ Architect's Note
Performance is a feature. In enterprise React apps, the most impactful optimisations in order: (1) code splitting at route level, (2) virtualising large lists, (3) React Query for server state caching, (4) debouncing expensive inputs. React.memo/useMemo/useCallback come much later and only where profiling shows they are needed. The React 19 Compiler will automate most render optimisation — focus on architectural decisions (code splitting, virtualisation, caching) which the compiler cannot do for you.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
React Technology Guide
Return to the React learning hub.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Python Developer Career Path
A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.
Sources
Sources / References
Use these React references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide React learning path
Browse the full React topic collection and learning order on SplashRide.
React Interview Prep
Practice React interview questions and scenario-based answers.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Python Developer Career Path
A practical route through Python fundamentals, automation, backend basics, testing, projects, interview preparation, and career growth.
React.memo
Master React.memo — the higher-order component for preventing unnecessary re-renders. Learn when it helps, when it hurts, and how to use it correctly with useCallback and useMemo.
Lazy Loading
Master React lazy loading — the technique for reducing initial bundle size by splitting code into chunks that load on demand. Learn React.lazy, Suspense, and route-based code splitting.