Rootstack

Optimize performance with code splitting in React

December 04, 2023

Tags: Technologies

react

 

It is common for SPAs (single-page applications) to split app functionality into multiple independent components. More often than not, only some components need to be loaded and rendered at a time. For example, if using a router, only the components relevant to the current route need to be loaded. However, by default, build tools such as Vite and Webpack bundle all code in a single file. 

 

If using a proper build tool, React can allow us to implement code splitting by separating component code into multiple independent files that are only loaded when needed. 

 

You should consider code splitting if: 

 

  • You have a large application with multiple independent components - that is to say, they are rarely or never rendered all at once. You have certain components that are very rarely used. 
  • Your application is divided into a small number of parts that are very large, and are not used all at once, but all exist within the same SPA. 

 

Code splitting might not be ideal if: 

 

  • Your application is small and does not have much code that could be split. 
  • You are not using a build tool that supports code splitting. 

 

 

react

 

Using lazy with import 

 

Code splitting can be achieved in React by using the lazy function, along with ESModule's import. In Vite, for example, import tells the build process that a certain import can be split from the main bundle file. 

 

lazy is included as part of React's core. It takes a function that must return a promise, or a promise-like _"thenable" object. In our case, import returns a promise. lazy will only call the function and start the promise when the component needs to be rendered, thus achieving proper lazy loading. 

 

This is especially useful when using it to lazy-load components in a router, so let's make an example of that: 

 

import { BrowserRouter, Route, Routes } from 'react-router-dom'; 
import { lazy } from 'react'; 
// We will only load the login component's file whe needed 
const Login = lazy(() => import('./login')); 
function Router() { 
return ( 
<BrowserRouter> 
<Routes> 
<Route path='/' element={<p>Default page</p>}/> 
<Route path='/login' element={<Login />}/> 
</Routes> 
</BrowserRouter> 
); 
} 
export default Router; 

 

react

 

Bonus: Suspense 

 

When a lazy component must be rendered, a small amount of time passes while its file is loaded from the server. Hence, it is recommended to add some loading behavior while it loads, instead of having the app freeze. This is where React's <Suspense /> component comes in handy. 

 

<Suspense /> allows us to display a fallback component while another is waiting on a promise (among other uses). In our case, we'll use it to update our previous example in such a way that a "loader" component is shown while the Login component loads.

 

// ... 
import { lazy, Suspense } from 'react'; 
// ... 
<Routes> 
... 
<Route path='/login' element={ 
// Assume that we have defined a <Loader /> component elsewhere <Suspense fallback={<Loader />}> 
<Login /> 
<Suspense/> 
}/> 
</Routes> 

 

react

 

Benefits of code splitting in React

 

Faster home page loading

 

By breaking your code into smaller chunks, you can reduce the amount of JavaScript that needs to be downloaded and executed when a user loads your app for the first time. This leads to a faster initial page load time, which improves the overall user experience.

 

Improved performance

 

Smaller code packages can result in faster execution times, as the browser can load and parse smaller files more quickly. This is particularly beneficial for users with slower network connections or less powerful devices.

 

Efficient use of resources

 

Code splitting allows you to load only the code necessary for the current view or functionality. Unnecessary code is postponed until it is actually needed, which can lead to more efficient use of resources.

 

Optimized caching

 

Smaller code packets are more likely to be cached by the browser. When a user revisits your site, the cached code can be reused, reducing the need to re-download the entire app and speeding up subsequent visits.

 

Better user experience

 

Faster loading times and improved performance contribute to a better overall user experience. Users are more likely to interact and return to a web application that provides a fluid and responsive interface.

 

We recommend you on video