Web Performance Case Study: webpack splitChunks
Tags: performance, webpack, webperf, javascript
Published: 2021-06-03 17:43:04

Hello there! I've just finished optimizing my last commercial project, and now, I want to share what I've learned. So, I've decided to start a series of articles.

In this article, I want to share with you knowledge about webpack's optimization.splitChunks functionality. That functionality is a part of the webpack since version 4 before It was an external plugin called SplitChunksPlugin. It provides a way to split your bundle into several parts.

# When can it be useful?
It can help you at least in two kinds of cases:

- When you have a single entry, you can separate vendors for a better cache strategy
- When you have many entries, you can separate common parts

Let's take a look at examples of both cases.

## Single entry

Let's imagine that we have a bundle that contains react app. It includes JavaScript code from an `app` directory and several npm packages from the `node_modules` directory:


![Initial bundle for single entry](https://cdn.hashnode.com/res/hashnode/image/upload/v1622567350860/K4TpTZLWs.jpeg)

Our bundle's name contains a `contenthash` for cache validation in the browser. When we change some code in our app, we create a new bundle that includes a different `contenthash`, and users will download it again. Frequently we'll change code inside our `app` directory and not change our npm dependencies, but our users will anew download the whole bundle. Here is where splitChunks can help us.

We can separate our bundle into two parts:
- code inside `app` directory
- code inside `node_modules`

In this way, when we'll change a code inside the `app` directory, our users will download only that part.

Let's do it!

To do that we need to add that code to our webpack config:

```javascript
{
  entry: {
    ... // here is your entry
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: /node_modules/,
          chunks: 'initial',
          filename: 'vendors.[contenthash].js',
          priority: 1,
          maxInitialRequests: 2, // create only one vendor file
          minChunks: 1,
        }
      }
    }
  }
}
```

Now our bundles will looks like that:

![Final bundle for single entry](https://cdn.hashnode.com/res/hashnode/image/upload/v1622567369138/vzbQGgh7o.jpeg)

How you can see we don't reduce bundle size, but we save some kb of traffic for our users in case when we change only one part of code.

You can get more control of what will be added to bundle by passing function instead of regexp as test:
```javascript
{
  entry: {
    ... // here is your entry
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        react: {
          test(module) {
            // `module.resource` contains the absolute path of the file on disk.
            return (
              module.resource &&
              module.resource.includes('node_modules/react')
            );
          },
          chunks: 'initial',
          filename: 'react.[contenthash].js',
          priority: 1,
          maxInitialRequests: 2,
          minChunks: 1,
        }
      }
    }
  }
}
```

In this case will be created bundle that will contain only code of react package.

## Many entries

Assume we have three entries like that:

![Initial bundles for many entries](https://cdn.hashnode.com/res/hashnode/image/upload/v1622569976386/wFTEXdkW9.jpeg)

We can move common code to separate bundle:

```
{
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: /node_modules/,
          chunks: 'initial',
          filename: 'vendors.[contenthash].js',
          priority: 1,
          maxInitialRequests: 2,
          minChunks: 3, // count of entries
        }
      }
    }
  }
}
```

Now our bundles may looks like that:

![Final bundles of many entries](https://cdn.hashnode.com/res/hashnode/image/upload/v1622571307268/9QU4TT4tg.jpeg)

We didn't reduced size of javascript needed for page, but we reduced total size of bundles and now we can cache common bundle across pages, and it's cool!

# That's it

Now you know how you can use the splitChunks to improve UX in your app, read [documentation](https://webpack.js.org/plugins/split-chunks-plugin/) for more detais and try it out!

Thank you for reading! This is the first article of the series about web performance, click on the `Follow` button to see future articles and motivate me to write them.

Follow me on Twitter: https://twitter.com/paulcodes_tech, there I'll share with you some tips and tools for Frontend developers.

Answer me in comments:
- Did this article was helpful?
- Do you like the pictures I provide?
- Will you try it out?
- Do you want me to provide a repository for this and future articles?
- Any other feedback :)