React LAZY

Introducing How Lazy Loading And Code Splitting Can Improve The Performance Of Your React Application.

Saumya Singh Nov 28

What is lazy loading?

Lazy loading is the technique of rendering only-needed or critical user interface items first, then quietly unrolling the non-critical items later. It is now fully integrated into core react library itself. We formerly used react-loadable to achieve this but now we have React.lazy() in react core.

To get a better idea about how exactly does react code bundling and splitting works, there is no better documentation than the official React docs for Code splitting and React.lazy.

Pre-requisite Inspector tools for analysing React performance:

Here’s a mini example of what we want to achieve!

Component rendering without Lazy Loading:

Without Lazy Loading

import React from 'react';
import Bounce from '../Bounce/index'
import Rotate from '../Rotate/index'

class Home extends React.Component {
    render() {
        console.log('Home');
        return (
            <div>
                <Bounce />
                <Rotate />
            </div>
        )
    }
}

export default Home;

Component rendering with Lazy Loading:

With lazy loading

import React, { Suspense } from 'react';

const Bounce = React.lazy(() => import('../Bounce/index'))
const Rotate = React.lazy(() => import('../Rotate/index'))

class Home extends React.Component {
    render() {
        console.log('Home');
        return (
            <div>
                <Suspense fallback={<div>loading first comp...</div>}>
                        <Bounce />
                </Suspense>
                <Suspense fallback={<div>loading second comp...</div>}>
                        <Rotate />
                </Suspense>
            </div>
        )
    }
}

export default Home;

No clue about what’s happening?

Let’s dig more into it. But before that, let’s explore why we need it.

What is the use of React Lazy Load?

Normally, when the application compiles and runs, our code is bundled into a single javascript file that is passed to the browser, but as our application grows, the bundle gets very heavy in size and cumbersome. It directly hampers the performance of the application as loading such a heavy file on initial load takes too much time, thus making our application slow.

So, here comes React.lazy() to the rescue!

React.lazy() performs lazy loading through Code Splitting. Here, code splitting means that our code is now not bundled in a single file, rather it is divided into smaller chunks (javascript files), and each chunk is loaded lazily, that is, as and when required.

For example, a page might consist of various assets or nested component or heavy re-rendering components like animation component. In this case, the page will take more time to load as compared to the simple one; In simple words the page will only be rendered once all the components are loaded, so the user will see a blank page for some time before the page is visible.

So, to avoid this, we can load the components lazily, that is, firstly only those components will be loaded that are currently on the viewport and the other components get loaded when they are needed. For example after a button click or maybe on scrolling, thus reducing the waiting time for the users.

How to implement it?

Before the release of React version 16.6.0, code splitting was done using react-loadable components but now React has a built in API for handling lazy loading and code splitting, that is, React.lazy().

It is a function in react that lets us load react components lazily through code splitting.

It takes a function as the only input and this function calls a dynamic import which then returns a Promise that resolves to a module containing a React component.

import React, { Suspense } from 'react';
const Component = React.lazy(()=>import('./Component/index'));

class Home extends React.Component {
  render() {
    return (
      <div>
        <h1>Lazy Components</h1>
          <Suspense fallback={<div>Loading…</div>}>
            <Component/>
          </Suspense>
      </div>
      )
    }
}

Here, Suspense is a component required by the lazy function basically used to wrap lazy components. Multiple lazy components can be wrapped with the suspense component. It takes a fallback property that accepts the react elements you want to render as the lazy component is being loaded.

What is the benefit of using it?

Suppose, we want to create a screen that contains different layers containing different components performing some animations, so using normal react imports we will achieve the target but the loading time will be enough to annoy the users, so to achieve the target as well as to reduce the waiting time for users we can use this combination.

For better understanding, we are going to create a page that contains five different components with different animations.

import React, { Suspense } from 'react';

const Bounce = React.lazy(() => import('../Bounce/index'))
const Rotate = React.lazy(() => import('../Rotate/index'))
const FadeIn = React.lazy(() => import('../FadeIn/index'))
const Flip = React.lazy(() => import('../Flip/index'))
const FadeOut = React.lazy(() => import('../FadeOut/index'))

class Home extends React.Component {
    render() {
        console.log('Home');
        return (
            <div>
                <Suspense fallback={<div>loading first comp...</div>}>
                        <Bounce />
                </Suspense>
                <Suspense fallback={<div>loading second comp...</div>}>
                        <Rotate />
                </Suspense>
                <Suspense fallback={<div>loading third comp...</div>}>
                        <FadeIn />
                </Suspense>
                <Suspense fallback={<div>loading fouth comp...</div>}>
                        <Flip />
                </Suspense>
                <Suspense fallback={<div>loading fifth comp...</div>}>
                        <FadeOut />
                </Suspense>
            </div>
        )
    }
}

export default Home;

So, when it is created without using lazy loading, on the initial load only, all the 5 components are loaded and bundled into the main chunk.

We can see that here the load time is 294ms, as all the components are loaded in it only. The entire DOM content takes 277ms to load in the initial go.

But when the same page is loaded with lazy loading, only the Bounce component is loaded first.

Here we can see that different chunks are created for all the components and the load time is 211ms, as only one component is loaded initially, and the DOM content is loaded in 163ms.

Understanding chunks

For better understanding of code splitting and how our main chunk looks like with and without code splitting, we can use a tool called source map explorer.

Main chunk is the file that is loaded initially.

Source map explorer is a npm package used to visualize a bundle.js file in any of the format such as, an HTML page or json file, etc.

So, when we visualize our main.chunk.js file implemented without lazy loading using this tool, we obtain this result:

Here we can see that the size of our main chunk is 9.25KB and it contains all the animated components irrespective of whether it is present on viewport or not.

Now let’s see the result of same file when implemented with lazy loading and code splitting:

Yes, the file size has decreased to 4.48KB because now it does not contain all the components within it, rather now each component has its own chunk file.

Thus, it will take less time to load this chunk file rather than a file containing all the components within it.

Performance Observation Using Inspector

We can see the difference in loading time for the above page when it is lazily loaded and when it is loaded normally, using the Profiler or the Performance tab in chrome dev-tools.

To see this difference first open the inspector on chrome and then go to the performance tab. Once you are on the performance tab, click on the record button present at the top left corner. Once you click on record the profiling will start recording like this:

While it is recording you can perform scrolling so that the performance of the entire page is recorded and once all the components and their animations are recorded you can stop the recording. After few seconds, a performance summary will be presented to you in form of charts and data.

Clearly, we can analyse the performance via inspector logs: 

Animation without lazy loading

We can see that the load time is 16ms in the above implementation.

Animation with lazy loading

Here we can see that the load time is just 5ms!

Conclusion

By the above performance comparisons we can clearly see that there is some difference in loading time when a page is loaded lazily and normally, but here the difference is very small because there are only five components. Imagine if you have to build a page containing hundreds of components. In that case this load time difference will be much higher.

Thus, lazy loading can really boost the performance of your application.

Here’s the link to the repo containing the above project:

https://github.com/Saumyasingh28/React-lazy-loading

I hope you got to learn usage and benefits of React lazy loading.

I am a software developer at GeekyAnts, working on React and learning other new technologies.

Thanks to Ruchika Gupta for all her technical help on this article.

 

2017 © All rights reserved. Sahu Soft India Pvt Ltd.