This page looks best with JavaScript enabled

Webpack - Preserve Class Names During Minification

 ·   ·  ☕ 3 min read

Suppose you have the following ES6 code:

1
2
3
class MyFancyService {
    // ...
}

And you want to have a refactor safe way to output the service name without instantiating an object. With some googling, you will probably use the following approach:

1
2
const serviceName = MyFancyService.name;
// and use serviceName in some way

This will work fine in dev, until you decide to minify it with webpack. You see, by default, class names will be minified, and at runtime the above code line will become something like Ab.name, which is far from desired output.

If you use this name to register an AngularJs component, or have any other hard dependency on it, you will get a runtime error and application will most likely crash.

As always, there are multiple ways to solve the problem. If your minification plugin supports it, you should provide a flag that would tell it not to minify class names. Usually you should consult the official documentation of the plugin, webpack docs, Stack Overflow or otherwise.

I am using esbuild-loader with webpack, so I will provide an easy fix for this scenario. Just add keepNames: true in the options. Ignore the …, it’s only there to give a better idea of the document structure, skipping unnecessary details:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const { merge } = require('webpack-merge');
const { ESBuildMinifyPlugin } = require('esbuild-loader')

module.exports = (env) => {
  return merge(common(env), {
    mode: 'production',
    // ...
    optimization: {
      // ...
      minimizer: [
        new ESBuildMinifyPlugin({
          keepNames: true,
        }),
        // ...
      ],
    },
  });
}

That’s it, now your production build will preserve class names and will work exactly like your dev build. If you are wondering why I am using function syntax - it’s a lot easier to incorporate environment variable support with it. Object syntax is very limited in this regard.

JS world moves pretty quickly, it is sometimes difficult to find a working combination of tool versions, so I will provide a list of package versions from package.json.

1
2
3
4
5
6
7
8
{
    "dotenv-webpack": "7.0.3",
    "esbuild-loader": "2.15.1",
    "webpack": "5.51.1",
    "webpack-cli": "4.8.0",
    "webpack-dev-server": "4.0.0",
    "webpack-merge": "5.8.0"
}

If you want to know more about other flags available in esbuild, you should take a look at their Github page. Take a look at tickets, releases, take part in discussions and perhaps even contribute. For example, here is a commit for when keepNames was introduced.

esbuild-loader could be lagging behind the official esbuild version, please keep that in mind. It is by design, to make sure only stable features are available for use in their package. Fortunately for this issue, the fix was put in on Nov 11, 2020, giving it enough time to appear under esbuild-loader umbrella.


Victor Zakharov
WRITTEN BY
Victor Zakharov
Web Developer (Angular/.NET)