WittCode💻

Why Your Production Bundles Are Huge!

By

Learn common causes of large production bundles. To demonstrate, we will bundle a React application for production using Webpack.

Table of Contents 📖

Large Bundle

Below is the output of a React bundle for a small application. Notice how the bundle.js file is 1.6 MB in size. This is very large for such a small application.

npm run build

-rw-r--r--  1 wittcode  staff  1622657 Sep  3 11:27 bundle.js
-rw-r--r--  1 wittcode  staff      971 Sep  3 11:27 bundle.js.LICENSE.txt
-rw-r--r--  1 wittcode  staff      244 Sep  3 11:27 index.html

There are three main reasons for bundles this large: assets, dependencies, and environment variable settings.

Handling Assets

First lets look at the assets. This application consists of images, all of which are being included in the bundle. Check out the configuration below.

{
  test: /\.(png|svg|jpg|jpeg|gif)$/,
  type: 'asset/inline'
}

This configuration tells webpack to inline images. This will include them in the bundle. Instead, we can make separate calls for the images. We can do this by setting the type to asset/resource.

{
  test: /\.(png|svg|jpg|jpeg|gif)$/,
  type: 'asset/resource'
}
npm run build
  
-rw-r--r--  1 wittcode  staff  146705 Sep  3 11:34 bundle.js
-rw-r--r--  1 wittcode  staff     971 Sep  3 11:34 bundle.js.LICENSE.txt
drwxr-xr-x  6 wittcode  staff     192 Sep  3 11:34 images
-rw-r--r--  1 wittcode  staff     244 Sep  3 11:34 index.html

Change the type to asset/resource causes Webpack to emit the images as files in the bundle and export their URL. Notice how the bundle size is now 146.705 kilobytes.

Handling Dependencies

The other cause for large bundles is dependencies. When bundling, Webpack will ignore a package if it has not been imported and used. For example, installing React MUI will keep the bundle size the same.

npm i @mui/material @emotion/react @emotion/styled

ERROR: React MUI requires Emotion dependencies.

npm run build

-rw-r--r--  1 wittcode  staff  146705 Sep  3 12:17 bundle.js
-rw-r--r--  1 wittcode  staff     971 Sep  3 12:17 bundle.js.LICENSE.txt
drwxr-xr-x  6 wittcode  staff     192 Sep  3 12:17 images
-rw-r--r--  1 wittcode  staff     244 Sep  3 12:17 index.html

However, as soon as we import something from the library and use it, it will be added to the bundle.

import {createRoot} from 'react-dom/client';
import './assets/styles/globals.css';
import App from './components/App';
import Stack from '@mui/material/Stack';

const root = createRoot(document.getElementById('root'));
root.render(<Stack><App /></Stack>);
npm run build

-rw-r--r--  1 wittcode  staff  215163 Sep  3 12:18 bundle.js
-rw-r--r--  1 wittcode  staff    1154 Sep  3 12:18 bundle.js.LICENSE.txt
drwxr-xr-x  6 wittcode  staff     192 Sep  3 12:18 images
-rw-r--r--  1 wittcode  staff     244 Sep  3 12:18 index.html

This is why it is important to install packages that are necessary. Large packages can bloat the bundle tremendously. Module bundlers also generally come with a way to exclude certain modules from the bundle. For example, we could exclude the packages React and React DOM from the bundle with Webpack.

externals: {
  react: 'react',
  'react-dom': 'react-dom'
}
npm run build

-rw-r--r--  1 wittcode  staff  75583 Sep  3 12:22 bundle.js
-rw-r--r--  1 wittcode  staff    432 Sep  3 12:22 bundle.js.LICENSE.txt
drwxr-xr-x  6 wittcode  staff    192 Sep  3 12:22 images
-rw-r--r--  1 wittcode  staff    244 Sep  3 12:22 index.html

Environment

The final common cause is environment variables. Specifically, not setting the environment as production. For example, in Node the NODE_ENV variable determines the type of environment. Setting it to production enables certain features that are only available in production. One of these features for Webpack is code minification.

mode: 'development'
npm run build

-rw-r--r--  1 wittcode  staff  545160 Sep  3 12:25 bundle.js
drwxr-xr-x  6 wittcode  staff     192 Sep  3 12:25 images
-rw-r--r--  1 wittcode  staff     257 Sep  3 12:25 index.html

Here, setting the mode to development creates a much larger bundle.