For modern front-end applications, performance is a must. For React developers, code optimization and improving the performance of your application can be done in different ways, some of which include the use of third-party libraries and React native optimizations like code splitting and dynamic imports.
In this article, we will look at improving performance in React applications with dynamic imports. We’d also look briefly at other ways of doing this with React.lazy(), React.Suspense and Loadable Components.
While You Are at It, Why Not Learn More About React 18 and It’s New Features?
What Are Dynamic Imports?
One of the best ways to maintain good performance for modern React applications is to hold off loading some parts of a web page until a user needs them. This can be done by holding off importing components into a React application if it is not immediately needed for a page to load and bundle.
Dynamic import is a modern JavaScript feature that imports files similar to Promises. Let’s see the code below.
import Home from "Pages/Home.js";
import About from "Pages/About.js";
import Contact from "Pages/Contact.js";
import Blog from "Pages/Blog.js";
import NewsLetter from "Pages/Newsletter";
In the code block above, we imported the files using static import, and this will bundle all files together when webpack runs through the code above. We will look at dynamically importing the components into the React app. We will do that in the code block below:
const module = await import ('/modules/myComponents.js');
Unlike statically imported components, dynamic imports are similar to node.js, meaning they’re asynchronous and only import your components and files when they’re needed.
How To Dynamically Render Components in React?
In this section, we will dynamically render React components. For example, let’s build a simple navigation for a website used by different users in different countries. We will show countries 1, 2, and 3. The website for country 1 contains multiple navigations and content, as shown below:
<div>
<Home2 />
<About1 />
<Bio3 />
</div>
Another user is using the same website but with a different build in country 2, as seen below:
<div>
<Home1 />
<About3 />
<Bio1 />
</div>
As seen, for this application, there are a lot of components. Here, we will create all the components needed for our application in different countries and then map our components before dynamically rendering them to users according to their countries. Let’s do that below:
const componentMapping = {
Home1,
Home2,
Home3,
About1,
About2,
About3,
Bio1,
Bio2,
Bio3
};
Next, we can render pages for a user in Country 1, we will do that below:
const Country1 = ['Home2', 'About1', 'Bio3'];
and for users in Country 2:
const Country2 = ['Home1', 'About3', 'Bio1'];
And using dynamic rendering for the components:
// < WebAppconfig={Country1} />
// <WebApp config={Country2} />
const WebApp = (props) => {
return (
<div>
{config.map((componentName) => componentMapping[componentName];
return <Component />;
})}
</div>
);
};
In the code above, we list how to map through all our components and render only when one is needed.
When To Use Dynamic Imports?
Although dynamic imports are a great way to improve the performance of your React applications, there are better use cases for using dynamic imports in React apps.
- Code Modulation: Dynamic imports can be used when there’s a need for code modulation and fetching data from a server. An example can be found in server-side rendered applications.
- Dynamic imports can be used when components are not needed when an application is still loading.
- Conditional imports are an excellent use case for dynamic imports; here, a module or component is only imported on pages where they’re needed and when needed in an application.
React.lazy()
The React.lazy() function allows you to render a dynamic import as a regular component. Basically, React.lazy() makes a call to a dynamic import and returns a promise. This can be seen below:
import Blog from 'Pages/Blog.js';
After:
import React, { lazy } from "react";
const Blog = React.lazy(() =>
import('./Pages/Blog'));
In the code above, React.lazy() will bundle Blog page when the component is rendered on a web page. The page is now loaded, this will ensure that a chunk of Blog.js page is loaded when it’s rendered.
In React, lazy components are usually rendered inside a Suspense component, which allows us to show fallback content, most times a loading icon, while users wait for a lazy component to load.
In our next section, we will look at React.Suspense and how to use it to improve the performance of our React applications.
React.Suspense()
React.Suspense allows React developers to conditionally suspend the rendering of a React component until it is loaded. React.Suspense provides a fallback prop that accepts a React element which either is a JSX snippet or a React component.
When users visit a page using React dynamic imports, oftentimes they experience a blank page screen, this is done while the application loads the module, this can also cause errors as a result of slow internet connectivity for some users. React.lazy() and React.Suspense when combined solves this issue for users.
To do this, use React.Suspense to suspend the rendering of a component until all dependencies are lazy-loaded, React.Suspense will also display your fallback UI for the user.
import React, { lazy, Suspense } from 'react';
const Blog = lazy(() => import('./Pages/Blog'));
const About = lazy(() => import('./Pages/About');
const Home = () => {
return (
<div>
<Suspense fallback={<div>Hi, This page is Loading...</div>}>
<section>
<Blog />
<About />
</section>
</Suspense>
</div>
);
}
In the code block above, we are lazy loading the Blog and About components. There are dependencies of the Home component, meaning the Home needs the pages to render completely.
We used React’s Suspense
component to suspend the Home page until the dependencies of the other pages are loaded. When the page is loading, the user sees the application’s UI for the fallback.
<div>Hi, This page is Loading...</div>
Loadable Components – Using Loadable Components for Imports
Another way to dynamically load pages and components in React is using a third-party library called Loadable Component.
Loadable components is a React library for code splitting, dynamically loading React-based components, and prefetching your React components. It’s important to note that Loadable components are recommended by the React team and are not an alternative to lazy loading of your components.
Loadable components come out of the box with a Loadable() function for creating asynchronous components that can be imported dynamically in a React application. Although it works very similarly to React.lazy() it is not an alternative and does not replace lazy loading your React components and pages, React Loadable works better for server-side rendered applications. It can accept a fallback without the Suspense component. Loadable components use the Loadable() function to inject props from a component and support importing React components dynamically.
We can accept fallback without the need for a Suspense component. The Loadable() function can also inject props from the component and support full dynamic imports.
import { Routes, Route, Outlet, Link } from "react-router-dom";
import loadable from "@loadable/component";
import About from "./pages/About";
const LoadablePage = loadable((props) => import(`./pages/${props.page}`), {
fallback: <div>Hello, This page is Loading...</div>,
cacheKey: (props) => props.page
});
export default function App() {
return (
<div className="App">
<h1>React Loadable Component</h1>
<Routes>
<Route path="/" element={<AppLayout />}>
<Route index element={<About />} />
<Route path="Bio" element={<LoadablePage page="Bio" />} />
</Route>
</Routes>
</div>
);
}
In the code block above, we are using Loadable components to lazy load our components, About and Bio.
Conclusion
In this article, we explained what dynamic imports are, why we should use dynamic imports in our React applications. We also looked at different ways of making your React application performant with React.lazy(), React.Suspense() and Loadable Components, a third-party library, recommended by the React team, to optimize React applications.