Hi, I am Sanjeet Tiwari...
Let's talk about

Back to Notes

Code Splitting

Performance Web React

At the very basic level, a website is just HTML, CSS and JS being shipped to the client from a server. One way to improve the performance is to reduce the amount of JS code being shipped on initial load.

This is what Code Splitting is! In React, we can achieve this with the help of dynamic import, lazy and Suspense.

There can be many scenarios where code splitting is practical. Lets take an example of an application with multiple routes like - Home, About and Contact Us. If the user is on the Home page, then we don’t need to download the code for the other 2 pages.

Code Splitting is essentially - download when you need it!

Code Splitting a function

Let’s take an example of a sum function which we want to execute only on a button click.

import sum from './sum.js';

<button onClick={() => alert(sum(2, 3))}>Click</button>

Here, on click of the button, an alert pops up and shows the result of the sum function which is imported from a different file.

What if, we want to load the code of sum function only when the button is clicked ?

We can do that by using dynamic import. Dynamic import returns a promise, which when resolved gives out a module object which can be used to access default and named exports.

<button onClick={() => {
    import("./sum.js").then(module => {
        // module.default if we want to use default export
        alert(module.sum(2, 3))
    })
}}>
    Click
</button>

Code Splitting a React Component

Code Splitting a React component is possible because a utility in React which goes by the name lazy.

It takes in a Promise which loads a component. It can be used with a dynamic import like this -

const MyComp = React.lazy(() => import("../components/MyComp"))

Now, till the time MyComp component is encountered, React will NOT load the code for MyComp.

But still while using this component in our React tree, we will experience an error, as the component MyComp is not available right away in the initial load.

React needs to know which components has the potential to lazy load. The way we can tell React is by wrapping the lazily loaded components by Suspense component.

<Suspense fallback={<h1>Loading...</h1>}>
    <MyComp />
</Suspense>

Now, in the initial cycle, React knows that MyComp has the potential to lazy load, and will wait for the component’s code to get loaded.

While the component is being loaded, a fallback UI is shown to the user which is nothing but the fallback prop of the Suspense component.

One important thing to note - Once the code of the lazy loaded components have been downloaded, you might not see the fallback UI again, as the component is already downloaded, and React doesn’t need to re-download it, and wait for it.

Important rule for using lazy

If you are lazy loading a React Component, the component needs to be default exported. If it’s a named export, lazy utility might not be able to receive the component, as lazy is expecting a promised object with default property.

Let’s consider that MyComp is not default exported in its file. One way to fix the lazy problem would be -

const MyComp = lazy(() => {
    import("../components/MyComp").then(module => {
        return { default: module.MyComp }
    })
})

Video Sources

Speed Up Your React Apps With Code Splitting

Speed Up Your React Apps With Code Splitting

Web Dev Simplified

Last updated on 09-08-2024