Back

Improve React's performance using Webpack Bundle Analyzer

Improve React's performance using Webpack Bundle Analyzer

When building a web application, you must consider the size of the assets used. Such assets are JavaScript, CSS, and images. Large files of these assets will slow down your application, negatively impacting your user experience. Webpack allows you to analyze and optimize the performance of your web apps. The analyzer presents you with a visual representation of the contents and size of the application bundles. Webpack generates the bundles for your application build process.

The Webpack bundle analyzer helps analyze the contents and size of the bundles generated during the build process. This makes identifying large files easier and optimizing the code for better performance. Using the generated bundle, the analyzer identifies any potential performance bottlenecks your application is exposed to. This way, you can use the Webpack bundle analyzer to reduce the bundle size and improve the performance of web applications. This tutorial will teach you how to improve your React application performance using Webpack Bundle Analyzer.

Setting up the bundle analyzer with React demo app

You will require a sample application to set up the Webpack bundle analyzer with React. In this tutorial, I created a sample React app on this GitHub Repository. Ensure you clone the application to your local computer, then proceed to its created directory:

cd speed_dial_app

Install the dependencies:

npm i

You can test the application by running the following development server command:

npm run start

-

You should have the following sample demo application. You can set up the Webpack bundle analyzer with the crated React demo app. You need to install the webpack-bundle-analyzer package as a development dependency using the following command:

npm install -D @craco/craco webpack-bundle-analyzer

This will also install CRACO. CRACO (Create React App Configuration Override) is a configuration utility for Create React App. It allows you to extend and customize the build process of any Create React App projects without losing the benefits of the Create React App toolchain.

CRACO intercepts and modify the Webpack configuration used by Create React App. This provides a simple API for modifying the aspects of the Webpack configuration, including the build process’s entry point, output path, loaders, and plugins.

Once the above packages are installed for your project, create craco.config.js to hold the configurations for the analyzer as follows:

const BundleAanlyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
// import the plugin
module.exports = function () {
  return {
    webpack: {
      // append Webpack configuration
      plugins: [new BundleAanlyzerPlugin({ analyzerMode: "server" })],
    },
  };
};

This will set up the Webpack Bundle Analyzer plugin with a React app using CRACO. This configuration object contains a new instance of the BundleAnalyzerPlugin, with a configuration object that sets the analyzerMode option to “server”. This tells the plugin to open a browser window with a live server that displays the bundle analysis report.

Scanning the application

Your React app can now use the Webpack Bundle Analyzer plugin to analyze your Webpack bundles. The bundle analysis report will automatically open in your default browser to check your development server, allowing you to visualize the size of your app’s bundles.

To scan and detect the application performance, run the following command:

npx craco build

The above command will create an optimized production build and expose port 8888 to view the different bundle sizes. From 127.0.0.1, you should be able to get your bundles results as follows:

-

Analyzing results

From the above results, other than the core React modules, the following observations can be made:

  • The total bandwidth used to load the page is 710KB, as shown here:

-

  • Different modules of the Material UI package have been loaded, yet they are not being used by the current page, as shown in the below picture:

-

  • Index.js loads 103 additional modules as shown below:

-

Let’s see how you can fix these results.

Session Replay for Developers

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — an open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

Fixing results

To fix the Webpack bundle analyzer report results, you can consider the following optimizations tips:

  • Code splitting large files into smaller and more manageable chunks.
  • Removing unused code.
  • Compressing assets such as images and fonts.
  • Lazy loading resources only when they are needed.

To fix the above results, you will use the following methods:

  • Only load the material UI component without loading the entire package.
  • Conditionally show the page once you click a button.

To load the material components individually, edit the SpeedDial.js as follows:

  • Replace import {Box,SpeedDial,SpeedDialIcon,SpeedDialAction} from '@mui/material'; with:
import Box from '@mui/material/Box';
import SpeedDial from '@mui/material/SpeedDial';
import SpeedDialIcon from '@mui/material/SpeedDialIcon';
import SpeedDialAction from '@mui/material/SpeedDialAction';

This will only import what the application will use. To render the page conditionally, on App.js:

  • Import the necessary packages:
import React,{useState,Suspense} from 'react';
import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
  • Import the SpeedDial once it is needed for Lazy loading:
const SpeedDial = 
React.lazy(() => import('./SpeedDial'));

Inside the render function, maintain the show speed dial state:

const [showSpeedDial,toggleSpeedDial] = useState(false);
  • Show speed dial if showSpeedDial is true:
if (showSpeedDial) {
  return (
    <Suspense fallback={<CircularProgress />}>
      <SpeedDial />
    </Suspense>
  );
}
  • Else, show a button to toggle button visibility:

else return (
  <Button variant="contained" onClick={() => toggleSpeedDial(true)}>
    Show Speed Dial
  </Button>
);

This is the current application that displays a button for conditionally loading the Speed Dial:

-

Now start the analyzer:

npx craco build

Your output should have a minimized bandwidth:

-

From above, you can see the bandwidth has dropped from 710 KB to 296KB.

Conclusion

The Webpack bundle analyzer helps you analyze and know what to optimize for better performance of your applications. You can identify potential performance bottlenecks and optimize your code for improved performance, and this results in faster load times and better user experiences.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs and track user frustrations. Get complete visibility into your frontend with OpenReplay, the most advanced open-source session replay tool for developers.

OpenReplay