React  

How to Improve React App Performance Using Code Splitting and Lazy Loading?

Introduction

As your React application grows, so does your JavaScript bundle size. Large bundles take longer to download, parse, and execute, making your React app feel slow—especially on mobile devices or slow networks. One of the most powerful ways to improve performance is by using code splitting and lazy loading. These techniques allow your app to load only the required code initially and fetch the remaining code when needed. This creates a faster, smoother user experience. In this article, we will explain how code splitting and lazy loading work, why they matter, and how to use them effectively with React.

What Is Code Splitting?

Code splitting means breaking your JavaScript bundle into smaller chunks instead of loading one large file.

Why Code Splitting Improves Performance

  • Reduces initial load time

  • Sends only the required code to the browser

  • Improves Time to Interactive (TTI)

  • Enhances SEO and Core Web Vitals

Without Code Splitting

Your entire React app loads at once—even if the user needs only one page.

With Code Splitting

React loads only the code for the current page and fetches the rest when needed.

Using React.lazy for Component-Level Code Splitting

React.lazy() allows you to load components only when they are needed.

Basic Example

import React, { Suspense } from "react";

const About = React.lazy(() => import("./About"));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <About />
    </Suspense>
  );
}

How It Works

  • React.lazy() dynamically imports the component

  • Suspense shows a loading indicator while the component loads

When to Use

  • Large components

  • Pages in routing

  • Dashboard widgets

  • Modals, charts, maps

Code Splitting with React Router

You can lazy load entire pages using React Router.

Example

import { BrowserRouter, Routes, Route } from "react-router-dom";
import React, { Suspense } from "react";

const Home = React.lazy(() => import("./pages/Home"));
const Profile = React.lazy(() => import("./pages/Profile"));
const Settings = React.lazy(() => import("./pages/Settings"));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<p>Loading page...</p>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/profile" element={<Profile />} />
          <Route path="/settings" element={<Settings />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Benefits

  • Loads only the page user navigates to

  • Keeps initial bundle very small

Using Dynamic Imports for Function-Level Code Splitting

You can lazy load logic, not just components.

Example

async function loadMath() {
  const math = await import("./mathUtils");
  console.log(math.add(5, 3));
}

When Useful

  • Heavy utility functions

  • Analytics libraries

  • Third-party dependencies

Splitting Vendor Libraries

Large libraries like charting tools should not load upfront.

Example

const Chart = React.lazy(() => import("react-chartjs-2"));

Why It Helps

  • Reduces initial bundle size by offloading heavy libraries

  • Great for dashboards and admin apps

Lazy Loading Images for Extra Speed

Lazy loading isn’t limited to components—you can also lazy load media.

Example

<img src="image.jpg" loading="lazy" alt="demo" />

Benefits

  • Faster initial load

  • Less bandwidth usage

  • Useful for image-heavy applications

Using Suspense Fallbacks

The fallback UI appears while your code chunk loads.

Example

<Suspense fallback={<Spinner />}>...</Suspense>

Tips

  • Use skeleton loaders for better UX

  • Avoid layout shifting

Preloading or Prefetching Chunks

You can preload components to avoid delays.

Example

<link rel="preload" href="/static/js/About.chunk.js" as="script" />

When Useful

  • Pages users are likely to visit soon

  • Hover previews

  • Anticipated navigation

Best Practices for Code Splitting

  • Split by route first—biggest performance gain

  • Split heavy components (charts, maps, modals)

  • Avoid splitting extremely small components

  • Combine lazy loading with image compression

  • Use build tools (Webpack, Vite) for automatic chunking

  • Analyze bundle size using source-map-explorer

Tools for Measuring Bundle Size

Recommended Tools

  • Webpack Bundle Analyzer

  • Source Map Explorer

  • Vite Bundle Visualizer

These tools show which files are large and need splitting.

Conclusion

Code splitting and lazy loading are powerful techniques to speed up React applications. By breaking your bundle into smaller chunks and loading components only when needed, you significantly improve load time, performance, and user experience. Using React.lazy, Suspense, dynamic imports, and route-based splitting ensures your app stays fast and responsive—even as it grows. With these optimization strategies, your React projects will deliver better performance across all devices and network conditions.