Stud2design LogoBlog

React lazy, Suspense and loadable-components

publish date

20 January, 2020

read time

5 mins

coverSource: https://codepen.io/TaniaLD/full/oKxep

We all love to develop an amazing web application for the users, in the process we keep on adding things to the website to make it more interactive, as a result to this the bundle size of the website also start increasing and which then increase page load time. Believe me, no matter how good the resulting UI maybe the user today will not wait long enough for the site to load so its important that we keep the user engaged.


Inspiration behind the library

One of the solutions to the above mentioned problem is the major inspiration behind this library, the solution is to split our main bundle into small chunks of bundle then fetch those chunks only when they are required and not on initial loading.


Code splitting if put simply means splitting your code, while bundling your application, code-splitting helps you with decreasing the size of the main bundle by dividing it into small chunks on basics of certain concerns, say there is a hidden or less frequent used component in your page or a component which takes time to render then such component can be pushed into another bundle, (not the main bundle) this will decrease bundle size on the first load and thus increase page load speed. Code splitting can also come very handy when splitting your code based on routes, it can easily be configured into your projects.


What’s the react solution for code splitting?

React team very well understand the benefits and performance gain of code splitting and thus they provide us with an API for its implementation. In React 16.6 they rolled out React.lazy() and React.Suspense.


React.lazy() leverage the dynamic import feature available in ECMAScript to lazy load your components and pages, it takes a function that must call a dynamic import(), which then returns a Promise which resolves to a module with a default export containing a React component.


Here is how a dynamic import work 👇


import('./components/module').then((module) => {
// Do something with the module.
});

Since dynamic import returns a promise it also supports the await keyword.


React.lazy example


import React, { lazy, Suspense } from 'react';
import Avatar from './Avatar';
const Quotes = lazy(() => import('./Quotes'));
export default function () {
return (
<div>
<Avatar />
<Suspense fallback='Loading...'>
<Quotes />
</Suspense>
</div>
);
}

Edit Lazy and Suspense and Loadable


To use lazy load from react you will need to use React.Suspense, any component that needs to be lazy-loaded must be wrapped around with a Suspense. Suspense component from react helps you to provide a fallback for your lazy component. Suspense can appear anywhere above the lazy component, it need not be the immediate parent. Single suspense can be used for multiple lazy components with a common fallback. The fallback can be a something simple as a spinner 🌀 to what your product design team agrees on 😀


If React.lazy, then why use Loadable-components?

Before I mention the benefits of the lib, I want to say it is very easy to add loadable-components to your project, also while using loadable-component you can totally avoid binding your lazy component with Suspense.

import React from 'react';
import loadable from '@loadable/component';
import Avatar from './Avatar';
const Quotes = loadable(() => import('./Quotes'), {
fallback: 'Loading...',
});
export default function () {
return (
<div>
<Avatar />
<Quotes />
</div>
);
}

Edit Lazy and Suspense and Loadable

But the most important difference to point out is one that

React.lazy and Suspense are not yet available for server-side rendering.

Hopefully in future React will come up with the solution for server-side rendering, but till then loadable-components is a recommended solution from React.


Loadable-components are also compatible with the fully dynamic import, and here fully concentrate that you can pass a variable to import components/pages dynamically. Thus at build time, it can be decided which component has to be bundled separately depending on the value held by that variable. This feature leverage dynamic import from Webpack


Caveats

React.lazy and loadable-components currently only supports default exports. The workaround it is to first import name component in a module then export it as default as mention in react docs.

The one good practice while using Lazy, Suspense and loadable-component, which is highly recommended is to use Error Boundary above your lazy components to display an error state when there’s an error.


import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = loadable(() => import('./OtherComponent'));
const AnotherComponent = loadable(() => import('./AnotherComponent'));
const MyComponent = () => (
<div>
<MyErrorBoundary>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</MyErrorBoundary>
</div>
);


Now that you know, what loadable-components is used for I hope you can make a decision whether you need it in your project or not and how efficiently you can use it in your project, else React.lazy is always there to help.


Resources

React Lazy

Loadable-components