HomeAbout Me

React Performance: Code Splitting

By Daniel Nguyen
Published in React JS
July 14, 2025
2 min read
React Performance: Code Splitting

🚀 Code Splitting in React: Make Your App Load Faster Without Sacrificing Features

Imagine this: You build a stunning dashboard app packed with advanced visualizations using libraries like D3 and Three.js. Your users are excited—until they open your app and the login screen takes forever to load. What happened?

The answer: You’re loading too much JavaScript up front.

In this guide, you’ll learn how to fix that using code splitting—an essential technique for improving load times in modern React apps. You’ll explore:

  • React.lazy() and <Suspense />
  • On-demand loading with import()
  • Eager loading via hover or focus
  • Transitions and useSpinDelay to improve UX

Let’s dive in. 🏊‍♂️


📦 What Is Code Splitting?

Code splitting is the practice of breaking your JavaScript bundle into smaller chunks that load only when needed. Instead of shipping all features to the user upfront, you load parts of the code on demand—especially expensive features that aren’t used immediately.

Think of it like Netflix only streaming the episode you’re watching—not the entire season at once.


💡 The Core Idea: Less Code = Faster Load

Here’s a simple example of dynamic imports using native JavaScript:

import('/some-module.js').then(
(module) => {
// Use module exports here
},
(error) => {
// Handle loading error
}
);

React takes this a step further with built-in support for lazy-loading components.


⚛️ React.lazy + Suspense

React’s lazy() function allows you to dynamically import components. You wrap the lazy-loaded component with <Suspense /> to show a fallback UI while the code loads.

Example:

// SmileyFace.tsx
export default function SmileyFace() {
return <div>😃</div>;
}
// App.tsx
import { lazy, Suspense } from 'react';
const SmileyFace = lazy(() => import('./SmileyFace'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<SmileyFace />
</Suspense>
</div>
);
}

This allows the bundle containing SmileyFace to be excluded from the main bundle—only fetched when needed.

🛠️ Try using Chrome’s Coverage tool to identify which code is unused at initial load.


🗺️ Use Case: Lazy Load a Globe Component

Let’s say your app has a beautiful 3D globe using heavy libraries like three.js. It’s impressive—but it shouldn’t slow down the login screen.

The Goal:

Only load the globe code after the user clicks “Show Globe.”

Solution:

import { lazy, Suspense, useState } from 'react';
const Globe = lazy(() => import('./Globe'));
function App() {
const [showGlobe, setShowGlobe] = useState(false);
return (
<div>
<label>
<input
type="checkbox"
onChange={(e) => setShowGlobe(e.target.checked)}
/>
Show Globe
</label>
<Suspense fallback={<div>Loading globe...</div>}>
{showGlobe && <Globe />}
</Suspense>
</div>
);
}

Open the Network tab in DevTools and watch the JavaScript chunk for Globe load on demand when you click the checkbox.

🧪 Bonus: Throttle the network to “Slow 3G” to simulate real-world loading scenarios.


⚡ Eager Load on Hover or Focus

Sometimes, lazy loading introduces delays that hurt UX. What if 99% of users end up clicking “Show Globe” anyway? Waiting twice—first for the app to load, then for the globe—is annoying.

Solution:

Start loading the module in the background as soon as the user hovers or focuses on the button.

let preloadGlobe = () => import('./Globe');
function App() {
const [showGlobe, setShowGlobe] = useState(false);
const Globe = lazy(() => preloadGlobe());
return (
<div>
<label
onPointerOver={preloadGlobe}
onFocus={preloadGlobe}
>
<input
type="checkbox"
onChange={(e) => setShowGlobe(e.target.checked)}
/>
Show Globe
</label>
<Suspense fallback={<div>Loading globe...</div>}>
{showGlobe && <Globe />}
</Suspense>
</div>
);
}

Now, the module begins loading before the user even clicks, leading to a faster, smoother experience.

📦 Pro Tip: Calling import() multiple times is fine—your bundler will ensure it only loads once.


✨ Transitions: Avoid Flashing the Fallback

React shows the <Suspense fallback /> immediately—even if the lazy component is already loaded. This can lead to an awkward flash of “Loading…” even when the component is ready.

To fix this, you can use useTransition to tell React this update is non-urgent. This delays the fallback UI and avoids flashing.

import { lazy, Suspense, useTransition } from 'react';
const Globe = lazy(() => import('./Globe'));
function App() {
const [showGlobe, setShowGlobe] = useState(false);
const [isPending, startTransition] = useTransition();
return (
<div>
<label
onPointerOver={() => import('./Globe')}
onFocus={() => import('./Globe')}
>
<input
type="checkbox"
onChange={(e) => {
startTransition(() => {
setShowGlobe(e.target.checked);
});
}}
/>
Show Globe
</label>
{isPending && <span>Preparing globe...</span>}
<Suspense fallback={<div>Loading globe...</div>}>
{showGlobe && <Globe />}
</Suspense>
</div>
);
}

You can also use the spin-delay package to delay the fallback from appearing too quickly:

import { useSpinDelay } from 'spin-delay';
const showFallback = useSpinDelay(isPending, {
delay: 300,
minDuration: 500
});

This adds polish and prevents jarring flashes of UI.


🧠 Summary: React Code Splitting Techniques

TechniquePurposeWhen to Use
React.lazy() + <Suspense />Load components on demandFor large, infrequently used features
import() on hover / focusPreload eagerlyFor features users often trigger
useTransitionDefer low-priority UI changesFor lazy components to avoid flashing
useSpinDelaySmooth loading transitionsWhen network speed is inconsistent

🧪 Test Your Optimization

Use Chrome DevTools:

  • Network tab: Throttle and watch chunks load.
  • Coverage tab: Check which JS was actually used.
  • Performance tab: Profile rendering and JS execution.

📚 Further Reading



Tags

#ReactPerformance

Share

Previous Article
React Performance: Concurrent Rendering

Table Of Contents

1
📦 What Is Code Splitting?
2
💡 The Core Idea: Less Code = Faster Load
3
⚛️ React.lazy + Suspense
4
🗺️ Use Case: Lazy Load a Globe Component
5
⚡ Eager Load on Hover or Focus
6
✨ Transitions: Avoid Flashing the Fallback
7
🧠 Summary: React Code Splitting Techniques
8
🧪 Test Your Optimization
9
📚 Further Reading

Related Posts

React Performance: Windowing
July 17, 2025
2 min
© 2025, All Rights Reserved.
Powered By

Quick Links

About Me

Legal Stuff

Social Media