DEV Community

Cover image for Code Splitting in React
NasreenKhalid
NasreenKhalid

Posted on • Updated on

Code Splitting in React

Code Splitting is a common practice in the world of application development, it basically is the phenomenon where you split the huge bundles/packages in your application into smaller chunks and download them only when required.

Problem Statement

To explain our problem statement, we can take the example of an app where user is on the login page and there is a possibility that this is not a valid user or even if he is a valid user he may not complete the login process and enter into my app, in both the cases we are wanting the user to download all of our app without considering the fact that this is a bad user experience as well as can result in a lesser performing application.

Code splitting technique helps avoiding the hassle of downloading all the files in an application in one-go, the root files can be downloaded immediately and the additional scripts are set to 'lazy' load after the page or application is interactive, thus improving the overall performance and user experience.

React applications can also grow humongous as you keep on adding components depending upon the nature of your application so here also we can employ the technique of code splitting where we create multiple bundles that can be loaded at runtime.

Code splitting allows us to keep the amount of code same and load the lines that will be required by the user or/and avoid loading those that may never be required by the user.

Dynamic Import

One way of implementing code splitting is through dynamic import. So, instead of doing this:

import { data } from './data';

console.log(data);
Enter fullscreen mode Exit fullscreen mode

We can implement the below syntax which will be automatically splitted by Webpack:

import("./data").then(data => {
  console.log(data);
});
Enter fullscreen mode Exit fullscreen mode

React.lazy

'lazy' is a React command that helps us to lazily fetch a component for example you can set the Products page to lazy load as shown below:

const ProductsPage = lazy (()=>import('../pages/products'))
Enter fullscreen mode Exit fullscreen mode

React.lazy takes a callback function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.
The lazy component should then be rendered inside a Suspense component, which allows us to show some fallback content (such as a loading indicator) while we’re waiting for the lazy component to load.

import React, {lazy, Suspense } from 'react';

const Products = lazy(() => import('./Products'));

function Main() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <Products />
      </Suspense>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

You can even wrap multiple lazy components with a single Suspense component.
Code splitting makes our react apps much faster and efficient since every time the browser is refreshed it will not download the whole component again and just fetch it from cache and execute instantaneously.

It is crucial to decide where in your app to introduce code splitting. You want to make sure you choose places that will split bundles evenly, but won’t disrupt the user experience.

Code Splitting in Routes

A good place to start implementing 'Code Splitting' is with routes. Most people on the web are used to page transitions taking some amount of time to load. You also tend to be re-rendering the entire page at once so your users are unlikely to be interacting with other elements on the page at the same time.

Below is an example of using lazy loading with React Router:

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const Products = lazy(() => import('./routes/Products'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<Products />} />
      </Routes>
    </Suspense>
  </Router>
);
Enter fullscreen mode Exit fullscreen mode

Code Splitting can also be helpful in setting the error boundaries in an app, for example when some modules fail to load due to some issue then error can be triggered gracefully. These errors are useful for the developers to help find the root cause of the issue and also provide a good user experience.

Avoid Waterfalls

It is very important to be very careful while you are splitting your code/components that run in a hierarchy.
For example, when you're code splitting at route level and your route is going to lazy load but the route itself loads two/three components, one of which is again lazy loaded and that component is again loading something else which is also lazy loaded so this will result in a messy waterfall and it will take a lot of time for your app to be actually interactive:

Image description

In order to avoid this situation, we can make use of the following points:

  • Make sure that you be very very smart while using the lazy loading and
  • Also, you can make use of 'Resource optimization' in javascript which is the 'preload' and 'prefetch' tag that instructs the browser to request a resource for a page/component about which we know that it will be lazy loaded at some point in time.

I will end this article by emphasizing that at the end of the day it is all about making your users happy and code splitting is one way of achieving that.

Image description

If you are looking for a learning experience that makes you a professional developer with hands-on coding skills, join one of the best courses here

Happy coding...

Discussion (0)