What is Lazy loading ?
You all must be already familiar with the term Lazy Loading, if not, it's a common asynchronous loading pattern where you defer loading a resource until it is actually needed.
In React v16.6, some interesting features were introduced, couple of them being React.lazy() and React.Suspense
, to power your application with component or route based code-splitting.
Note:
React.lazy and Suspense
are not yet available for server-side rendering (v16.13.0). If you want to do code-splitting in a server rendered app, we recommend Loadable Components. It has a nice guide for bundle splitting with server-side rendering.
Why is it needed?
JavaScript has evolved tremendously over the last few years. With Webpack, Gulp, Grunt and many more bundlers, you can achieve code-splitting by breaking your one large bundle into different bundles (or chunks) and loading them individually, instead of all at once, to reduce the impact on page load time.
With time, your application would grow and it could lead to increase in bundle size and could in turn impact page load time.
Let's jump into the code to understand this.
Suppose, you have an application with Home component, which has a dropdown menu on header. The UserMenu renders when user clicks on the profile icon.
In the scenario below, during the initial load, the UserMenu component will be part of the bundle.
import React from 'react';
import UserMenu from '../Menu/UserMenu';
class Home extends React.Component {
/* some logic */
render() {
{ isUserMenuOpen && <UserMenu /> }
/* do something else */
}
}
But you must be thinking, what issues this might create? This seems be good so far! No?
It does seem good for smaller applications. But when the application scales and feature set increases; with its implementation the bundle size increases as well, eventually increasing the page load time. Furthermore, users with low end devices and slower network adds on to the problem.
This is where React.Lazy and Suspense
come to the rescue!
Let's fix the current scenario by using this amazing feature. Create a file called LazyUserMenu.jsx
import React, { Suspense } from 'react';
const UserMenu = React.lazy(() => import('../Menu/UserMenu'));
const LazyUserMenu = props => {
<Suspense fallback={ <h1> loading ... </h1> }>
<UserMenu { ...props } />
</Suspense>
}
export default LazyUserMenu;
We have created a Lazy async UserMenu
component. And while the component is getting fetched, suspense helps you add a loading state to your view. Now, let's use LazyUserMenu
component instead of the other one.
import React from 'react';
import LazyUserMenu from '../Menu/LazyUserMenu';
class Home extends React.Component {
/* some logic */
render() {
{ isUserMenuOpen && <LazyUserMenu /> }
/* do something else */
}
}
Voila!! This is it. This way the LazyUserMenu
component will only be fetched when the isUserMenuOpen
state is set i.e., only when the component is required.
To check how does it work ?
Go to Network
tab in developer tools. Click on user profile icon to open the menu.
You will see the component getting downloaded as a separate bundle.
Benefits of using these components:
- Trimmed initial bundle size.
- Better initial page load time.
- Better performance on low end devices or devices with weaker network strength.
Conclusion
Lazy and suspense feature has great potential benefits with large feature-rich applications. Whenever you add a new feature to your project, try to evaluate its performance impact on the bundle. If you think the feature could be used on demand or may never be used in the user journey then Lazy and Suspense is the way to go!
Happy Coding!
Top comments (2)
Good explanation.
Crisp and clear.
Thanks for sharing.
Keep coding!
Short and simple. Well explained!