Lazy Loading In React

Abhimanyu Chauhan
May 9, 2019 · 6 min read

React uses bundlers like WebPack to package its code and deploy it, to the browser. This bundled package is used by the browser to render your React application.

Now imagine creating an application with hundreds of components. By default, the bundler will merge all those components into a single bundle.js and load your application. This will, in turn, increase the initial package size, which leads to an increase in the loading time.

*The size will further increase with the number of third parties used.

There is something called the 3-Second-Rule, which states that it takes approximately 3 seconds to grab customer attention. So if it is taking more time, the customer/user might not even stick around to check the final product, rather he might spend more time finding an alternate.

So what can we do to improve our performance and not make the very important customer of ours wait?

The answer is simple, load the components that are required first and load the others when they are required. This is what Lazy loading is, loading the application in parts, rather than in a single bundle.

Think about it you have an application with the following flow:

Home -> Login/Register -> User Dashboard -> Logout

By default, when you load a react application, it will load all the components at once. But do we, require the User Dashboard and Logout components, when the user has not even logged in. Rather we can load the Home and Login/Register components and this decrease the size by half increasing the load time. Once the user logs into the application, that is when we can load the other two components.

* If you are using create-react-app to create the boilerplate, the web-pack is already configured to support dynamic imports(Lazy-Loading). If you are creating building the code base from scratch, you will have to configure the web-pack accordingly.

Now we know the why let’s begin with the HOW?

In this article, I will be showing you two methods to implement Lazy Loading

  • First is by using React.lazy and Suspense(min react version 16.6.0).
  • Second by creating a higher order component(HOC).

So let’s begin by creating a demo react app. You can download/check my finished code on GitHub.

*I will be assuming you have basic knowledge of React and will directly move to the implementation.

I have my main component App.js, in which I will be defining two routes:

  • First is for Signup page which will be using the HOC method.
  • Second is for the Login page which will be using React.Lazy and Suspense.

Using React.lazy and Suspense

This feature was first introduced in React version 16.6.0, to introduce lazy loading in the ecosystem.

*Note: This is not supported in server-side rendering, yet.

In React, we use the import keyword to fetch the component which is basically a JavaScript module.

import Landing from ‘./Components/Layout/Landing’;

By default, import will fetch the module and merge it to the bundle file. What we require is an import, which is more dynamic in nature, meaning the import only occurs when it is required.

React.lazy makes this dynamic import possible, which is also easy to implement.

const Login = React.lazy(() => import(‘./Components/Login’));

React.lazy takes in a function as a parameter, which returns a promise from the dynamic import invocation. This promise is resolved to load the module containing the React component.

*Note: As of now React.lazy does not support named exports, so remember to use default export for components which you want to dynamically import.

export default Login;
export const abc = className; **Not Valid **

Once the module is loaded, it will return a new bundle with the Component merged to the previous code.

*Note: This updated bundle is also updated in the cache, meaning once a component is loaded, web-pack will not try to import the same component again.

As stated above, the dynamic import returns a promise, which means it takes time to get the module, update the bundle and load the required component. So we might need a fallback content, to display while the component gets loaded, this is where Suspense comes into the picture.

First, we need to import the Suspense module from React:

import React,{Suspense} from ‘react’;

We can think of the Suspense component as a HOC, which wraps the component defined using React.lazy, for example, Login in the below snippet.

<Suspense fallback={<div>Loading…</div>}><Login /></Suspense>

The fallback attribute/prop is where we define the content which will be displayed while the component gets loaded.

Login Component rendered using React.lazy and Suspense

To check whether our changes are working or not, we can check the dev-tools:

The 1.chunk gets called when the component in dynamically imported

The 0.chunk is the bundle without the components which will be called through dynamic import. After the Login component was called, another file 1.chunk was loaded, which contains the updated bundle.

*We can also define Error boundaries around the Suspense to display custom errors if the component fails to load.

Creating your own custom HOC

By creating our own custom higher order component to load components, we get the liberty to make any modifications as we require.

import React, { Component } from ‘react’;const lazyLoader = (importComponent) => {
return class extends Component {
state = {
component: null
}
componentDidMount () {
importComponent().then(cmp => {
this.setState({component: cmp.default});
});
}
render () {
const CustComponent = this.state.component;
return CustComponent ? <CustComponent {…this.props} /> : null;
}
}
}
export default lazyLoader;

Let's look at the invocation of this HOC, you might see the similarities in the calling methods with the React.lazy method.

const AsyncRegister = lazyComponentLoader(() => import(‘./Components/Register’));

As we can see, the component accepts a function as a parameter and returns the component lazyLoader.

The import gets resolved in the componentDidMount life-cycle hook, this is done to avoid any side effects. The state gets updated and the dynamically imported component gets returned.

The Register Component rendered using our custom HOC

Like in the above example, let’s check the dev-tools:2

2.chunk gets loaded

As we can see when Register component was called a new chunk was sent, with the updated bundle

*Note: we are spreading the props, to pass the props from the lazyLoader component to the imported component in this case CustComponent.

You can find the repository for the above example here.

Data Driven Investor

from confusion to clarity not insanity

Abhimanyu Chauhan

Written by

A UI /UX Designer and JS Enthusiast, with a passion for travelling and writing.

Data Driven Investor

from confusion to clarity not insanity

More From Medium

More from Data Driven Investor

More from Data Driven Investor

More from Data Driven Investor

More from Data Driven Investor

PowerPoint: The Most Underrated Diagram Tool

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade