Occasionally, you might encounter a situation where your application takes a while to load initially. Usually, this happens due to the size of JS files being too large. Consequently, this will result in a poor user experience as the user will have to wait for all the code to load, even those the user might not require. Code splitting comes in handy in these situations.

Code splitting is a technique used in React to improve performance and loading speed of web applications. The process involves breaking up the codebase into smaller segments that can be loaded individually on demand rather than simultaneously. This approach ensures that users only download the necessary code when required, resulting in faster load times and an enhanced user experience. Code splitting involves identifying parts of the code that are not needed right away. Subsequently, these parts are separated and loaded when their need arises.

Dynamic Imports

Code splitting is achieved in React using dynamic imports, which enable modules to load on demand. The import() function achieves dynamic imports, returning a Promise that resolves to the namespace object of the module. React 16.6 introduced two new features for implementing Dynamic imports: the React.lazy() function and the Suspense component. The components are loaded only when they are required using React.lazy() function. The Suspense component provides a fallback UI while the component is loading.

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

function App() {
  return (
    <Suspense fallback={<div id="loading-div">Loading...</div>}>
      <Home />
    </Suspense>
  );
}

export default App;

In the above example, the React.lazy() function is employed to load the Home component lazily. The Suspense component will show the loading div that is provided to the fallback prop while the component is loading. Thus, the Home component is only loaded when it is needed.

The components that are only needed on certain pages or the components that are only required after a specific user interaction are typically loaded using the React.lazy() function. The Suspense component improves the user experience by keeping the user engaged while the component is being loaded.

The below examples shows the improvement in loading time when the pages are loaded lazily. There are three pages in the below application. Let’s consider that the ‘About’ page in the application is not accessed frequently by the users or is very bulky in code. In the first example, the total loading time is around 600ms. In the second example, we have implemented code splitting. We are loading all the pages lazily. So, the code for the ‘About’ page will only be loaded when required. We can see that the loading time for the ‘bundle.js’ is reduced to 365ms. We can also observe that the code for the ‘Home’ page is loaded separately, and the code for the ‘About’ page is not loaded yet.

Initial loading time without code splitting
Initial loading time with code splitting

Strategies For Code Splitting

There are different strategies used for code splitting. The strategies for a specific application can be decided based on the requirements of that particular application. Some of the most common code splitting strategies are:

  1. Route-based code splitting – In this method, the code is split based on the routes in the application. i.e. The code for each route will be loaded only when the application is in that particular route. This strategy will help in avoiding loading code for unwanted routes, thus reducing the initial load time of the application.
  2. Component-based code splitting – In this method, the code is split based on the components in the application. The code for each component will only be loaded when the particular component is required. This strategy will help in avoiding loading a large number of components that the user may not even use or even loading a complex component that may take a large time to load which the user might not even need.
  3. Vendor-based code splitting – In this method, the code is split based on the packages or the third-party libraries used in the application. Only the code needed for the application is loaded instead of loading the entire package or library. This strategy will help in reducing the overall size of the application.
  4. Hybrid code splitting – In this method, a combination of the above strategies is used. This strategy will allow the code splitting to be more flexible and also allow customisability.

Best Practices For Code Splitting

Even though code splitting can be an effective technique for improving performance, there are some best practices that the developers need to ensure so that the code splitting is beneficial to their application.

  • Avoid splitting too much – It is important to ensure that the code is not split too much as splitting into too many small parts can lead to decreased performance, as each part will need an additional request to load. The code should be split in such a way that the chunks are large enough to be useful, but also ensuring that the parts are not so large that they affect the performance of the application.
  • Avoid unnecessary code splitting – Developers should also keep in mind that not all code needs to be split. It is important to analyze the application before splitting the code to ensure that the splitting is beneficial. Developers should also avoid code splitting the parts of the application that might be frequently used.
  • Testing and monitoring – Developers also need to ensure that the application is working as expected after the code splitting. Developers also need to ensure that the performance is consistent and also identify performance bottlenecks to make necessary optimisations.
  • Prioritize critical parts of the application – It is important to prioritise the parts of the application that are likely to impact performance such as large components, routes, or third-party libraries.

Overall, code splitting can be an effective tool to improve performance as well as the user experience of your React application. It can also reduce bandwidth usage as the data that is being transferred through the network is also getting reduced. This will also significantly improve the scalability of your application. Even though code splitting has these advantages, it requires careful planning and execution. By following the best practices for code splitting, you can significantly improve the performance of your application.