Faster React Page Loads With Lazy and Suspense
Tags: react, javascript, webpack, performance
Published: 2020-07-28 20:00:27

---
title: Faster React Page Loads With Lazy and Suspense
published: true
description: I'm showing a simple use case where React Lazy and Suspense can speed up your web application loading time. Comparing Lighthouse and React Bundle sizes
tags: react, javascript, webpack, performance
cover_image: https://miro.medium.com/max/1000/1*G_nobLabnvfcwtpVyMJ4vQ.jpeg
---

Third-party libraries, images and huge amount of static data can all influence your application bundle size. This can cause unexpected high loading times, which may lead to a bad first site impression. **React.Lazy** and **React.Suspense** are common techniques (as of mid 2020), to perform code splitting for bundle size reduction and speeding up page load. In this article I want to show quick you may add code splitting to your React application, highlighting the differences in performance (Lighthouse benchmark/check).

## The base application

The idea is that we have a React component, that just displays some static data from a JSON file. I have chosen the [programming-quotes-api](https://github.com/skolakoda/programming-quotes-api) in order to have some data that makes sense. This data is not being fetched at runtime, but put into a local JSON file, which means it will be bundled into the application. To make the data a bit bigger, I have duplicated its content.

The app boilerplate was created by the common `create-react-app` tool as described [here](https://reactjs.org/docs/create-a-new-react-app.html). From there on, I have created a React component, call it `VeryBigJokesList`, that displays the static content.

```jsx
import React from 'react'

import preDefinedJokes from './preDefinedJokes.json'

const VeryBigJokesList = ({ jokes = preDefinedJokes }) => {
  if (!Array.isArray(jokes)) {
    return <p>No jokes found.</p>
  }

  return (
    <ul>
      {
        jokes.map((joke, i) => <li key={i}>{joke && joke.en}</li>)
      }
    </ul>
  );
}

export default VeryBigJokesList;
```

## The non-lazy (eager) case

Usually, I would just import the `VeryBigJokesList` component and render it in the `App` component, created by the boilerplate.


```jsx
import * as React from 'react';

import VeryBigJokesList from './VeryBigJokesList';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <div style={{ maxWidth: 600 }}>
          <VeryBigJokesList />
        </div>
      </header>
    </div>
  );
}

export default App;
```

This causes to the user load all content from `VeryBigJokesList` when loading `App`, since it will be “placed” in the same final bundle. When building the application via `yarn build` or `npm run build`, you will see a list of all bundled files of your application.

![bundle1](https://miro.medium.com/max/700/0*PcTyTxw0IenkgCXN.png)

As you can see, the main bundle is yellow highlighted, indicating that its size may be too big. This makes sense, since the JSON data that `VeryBigJokesList` includes is roughly this size. When running a Lighthouse performance check, you should also see some loading specific issues.

![bench1](https://miro.medium.com/max/700/0*PaG4GHNO-o4nJ4kj.png)

## The lazy case

When planning to use [React.Lazy](https://reactjs.org/docs/code-splitting.html#reactlazy), you mostly need to consider the fact that `VeryBigJokesList` is being exported via `export default` and is put as a child (of any depth) of a React.Suspense component. Suspense allows you to render a fallback component (like a loading indicator), while its content is loading.

```jsx
import * as React from 'react';

const VeryBigJokesList = React.lazy(() => import('./VeryBigJokesList'));

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <div style={{ maxWidth: 600 }}>
          <React.Suspense fallback={<p>Loading list...</p>}>
            <VeryBigJokesList />
          </React.Suspense>
        </div>
      </header>
    </div>
  );
}

export default App;
```

Adjusting `VeryBigJokesList` to load lazily was rather simple. If everything worked well, you should see a loading text, before the list is displayed. When building the application, you should also see a difference.

![bundle2](https://miro.medium.com/max/700/0*sNPj4Gz4PjlIi29f.png)

The main bundle size has decreased dramatically, since the static JSON content has moved to a different chunk of the bundle. When running a Lighthouse performance check, you should see a difference in loading times.

![bench2](https://miro.medium.com/max/700/0*hX8U0S46urm1yCJx.png)

_Originally published at [https://mariusreimer.com](https://mariusreimer.com/blog/id/faster-react-page-loads-with-lazy-and-suspense) on July 26, 2020._