Code-Splitting in React

Hari Sapna Nair
Last Updated: May 13, 2022

Introduction 

In React, everything is bundled into a single package and served to the users. This negatively impacts the user experience as they get served a large chunk of unused code. This becomes a huge problem when the project's codebase increases and the initial loading time increases drastically. 

 

According to research done by Google, "53% of visits are likely to be abandoned if pages take longer than 3 seconds to load." Reducing the load time even by a fraction of seconds can give a huge revenue boost to the company. Hence it becomes essential to improve the site performance.

 

The site's performance can be improved if we serve only the code required in that scenario. This is done using a technique called code-splitting in React, which will be discussed in detail in this blog.

Bundling

Bundling is the process where the files in React are merged into a single file called a bundle. The bundle is then included on a webpage to load an entire webpage at once. Bundling is done using tools like BrowserifyWebpackRollup, etc., where the bundles are dynamically loaded at runtime. 

 

During the initial loading of the app

 

Let's look at an example,

 

greetings.js

export function greet(name) {
 return `Hi ${name}`;
}

 

App.js

import {greet} from "./greetings.js"

console.log(greet("Ram")); 

 

The corresponding bundle file would look like this,

 

Bundle.js

function greet(name) {
 return `Hi ${name}`;
}

console.log(greet("Ram")); 

 

Bundling decreases the calls needed to set up the page as the browser doesn't have to run separate files while loading the web app. It speeds up the page loading time and lowers the amount of traffic the page needs to handle. However, when a bundle grows in size, the overhead of interpreting and executing the code slows down the page load instead of speeding it up. 

 

To tackle this issue, in October 2018, React 16.6.0 introduced code-splitting in React.

Code-splitting in React

Code-splitting in React is a method of generating bundles that are loaded dynamically at runtime. Instead of downloading the entire webpage before users can use it, code-splitting allows us to split the code into small chunks, which are then loaded on demand. It also helps to make the code efficient because the bundle contains all required imports and files.

 

Browserify and Webpack support code-splitting. In React, create-react-appGatsbyNext.js, etc., provides a Webpack set-up to bundle the files. However, if you wish, Webpack can also be set up manually. 

import()

One of the best methods to introduce code-splitting into the app is through the dynamic import() syntax. Dynamically import means we only want to import a file and then load it when necessary. For dynamic import, we can import the direct path and then call the method needed using the .then method.

 

Code-splitting in React can be used as follows,

// code-splitting in react using import()
import("./greetings").then(greetings => {
 console.log(greetings.greet("Ram"));
});

 

Code-splitting in React starts automatically when Webpack comes across the import() syntax. 

React.lazy

The React.lazy is a function used to render a dynamic import as a regular component. It takes a function that makes a call to dynamic import().

Let's see an example to understand React.lazy.

 

The regular way of importing components

import React from "react";
import Navbar from "./Navbar"

 

Using React.lazy() for code splitting

// Code-splitting in react using React.lazy()
import React from "react";
const Navbar = React.lazy(() => import('./Navbar'));

 

This method will automatically load the bundle containing the Navbar when the component is first rendered. The function call returns a promise which resolves to a module with a default export containing the React component.

 

The lazy component is then rendered inside a Suspense component, showing some fallback content like a loading indicator while we wait for the lazy component to load. The fallback prop accepts any React elements that must be rendered while waiting for the component to load.

 

Code:

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

const App = () => {
 return (
   <>
// Suspense component added
     <Suspense fallback={<h1>Please Wait</h1>}>
       <Navbar />
     </Suspense>
   </>
 );
};

export default App;

Error Boundaries

In React, error boundaries are the components that catch errors in their child component tree, log those errors, and display a fallback instead of the component tree that crashed. They catch errors in lifecycle methods,  in constructors of the whole tree below them, or while rendering.

 

For example, in React, if a module fails to load in case of network failure, these errors can be handled using error boundaries. The error boundary can be used anywhere above your lazy components to display an error state. 

 

Code:

import React, { Suspense } from "react";
import ErrorBoundary from "./ErrorBoundary";

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

const App = () => {
 return (
   <>
// ErrorBoundary added to handle errors
     <ErrorBoundary>
       <Suspense fallback={<h1>Please Wait</h1>}>
         <Navbar />
       </Suspense>
     </ErrorBoundary>
   </>
 );
};

export default App;

Route-based

 

While introducing code-splitting in React, the developer must choose a place that splits bundles evenly but won't disrupt the user experience. Routes can be useful in this case.

 

Let us see an example to understand route-based code splitting in React. For this, we can use the react-router package along with React.lazy.

 

Code:

import React from "react";
import { BrowserRouter as Route, Switch } from "react-router-dom";

const Home = lazy(() => import('./routes/Home'));
const Courses = lazy(() => import('./routes/Courses'))
const About = lazy(() => import('./routes/About'))
const Profile = lazy(() => import('./routes/Profile'))

const App = () => {
 return (
   <>
// code-splitting in react using routes
     <Switch>
       <Route exact path="/" component={Home} />
       <Route path="/myCourses" component={Courses} />
       <Route exact path="/aboutUs" component={About} />
       <Route path="/myProfile" component={Profile} />
     </Switch>
   </>
 );
};

export default App

Frequently Asked Questions

1. Does code-splitting in React reduce the actual amount of code?

Ans:- No, it avoids loading codes that the user does not require at that particular time. This reduces the load time and improves performance.

 

2. How to do code-splitting in a server-rendered app?

Ans:- At present, Suspense is not available for server-rendered app and React.lazy can only work with Suspense. So we have to make use of loadable components.

 

3. Where should the suspense component be placed?

Ans:- The Suspense component can be placed anywhere above the lazy component.  

 

4. How to import named imports in React?

Ans:- Currently, React.lazy only supports default exports. So if the module we want to import uses named exports, we have to create an intermediate module that reexports it as the default. This is done to avoid pulling in unused components.

 

5. How many lazy components can be placed inside a single suspense component?

Ans:- There is no limitation. Hence multiple lazy components can also be wrapped with a single Suspense component.

Key Takeaways

In this blog, we discussed the concept of code-splitting in React and the various ways to include code-splitting in the React application.

 

Developers, if you are preparing for the next interview, check out the blogs 15 Most Frequently Asked React JS Interview Questions and 10 Best ReactJS Interview Questions. And if you are a beginner, check out the Top 5 skills to learn before you start with ReactJs to know the prerequisites to learn React.

 

We hope you found this blog useful. Feel free to let us know your thoughts in the comments section.

Was this article helpful ?
0 upvotes

Comments

No comments yet

Be the first to share what you think