How to speed up Angular CLI app with esbuild-loader
I'm JS developer with 13 years of professional experience. I'm always happy to teach my craft.
Search for a command to run...
I'm JS developer with 13 years of professional experience. I'm always happy to teach my craft.
No comments yet. Be the first to comment.
I’ve been working in programming for the last 16 years. Let’s see what changes I see in our industry that are enabled by generative AI. Rapid prototyping The last few months, I’ve been working on a set of WordPress plugins, related to event organizat...
Writing unit tests takes time and effort. Nonetheless, many teams insist on writing them anyway—that’s because of the benefits they bring to a project. Those benefits are mainly the following: fast feedback—unit tests speed up each iteration of twea...

Pure functions are the perfect case for unit testing. For a given input, we always expect the same output—there is no internal state involved. Let’s take a look at a few examples and some simple tests that check if the methods work as expected. Jasmi...

Let’s say you have a job interview in a few days. How should you prepare for it so that you can make an informed decision about joining the company, as well as make sure that your interests are taken care of? Prepare your questions An interview is a ...

Creating example projects is a common way of showing your skills to potential employers. Let’s take a look at what’s important to keep in mind when building personal projects with an eye toward impressing prospective employers. Simplicity Building ap...

A previews article in this series showed how to build Angular CLI app with esbuild. There are two downsides of this approach:
This article will try a different approach to harvest esbuild speed for your Angular CLI application. As I already shown in another post, using esbuild-loader provided minimization plugin can be pretty effective.
This is not an easy configuration. Getting it up & running made my head spin, and I started questioning my framework and tooling choices along the way. In the end, I got something working, but the results are not impressive. It probably deserves a heavier test, similar to the benchmark used in the post linked above.
Angular CLI used to have ng eject command to expose the webpack configuration. Unfortunately, since version 8, it's not available anymore. Instead, we can specify "projects.*.architect.build.builder" inside our angular.js to override the webpack config partially - without getting access to the whole thing.
This is the approach used in angular-builders project, which I used in this guide.
Here, I'll set up only ESBuildMinifyPlugin from esbuild-loader. The in the webpack article, it looked like better speed improvement than the loader itself. As angular is written in typescript, the loader can improve speed, but I'm afraid it will be an even bigger endeavor than this one.
For a starter, let's install the necessary dependencies:
$ npm install --save-dev @angular-builders/custom-webpack esbuild-loader
The configuration change can be tricky. First, let's add our webpack.config.js with changes we want to apply:
const { ESBuildMinifyPlugin } = require("esbuild-loader");
module.exports = (config, options) => {
// if you console log here, you can see what's inside the config
// remove 2 first minimizers, hoping they are the TerserPlugin
config.optimization.minimizer.shift();
config.optimization.minimizer.shift();
config.optimization.minimizer.unshift(
new ESBuildMinifyPlugin({
target: "es2015", // Syntax to compile to (see options below for possible values)
})
);
return config;
};
To make it work, let's update angular.json:
"projects": {
"esbuild-loader-ng-cli": {
...
"architect": {
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-builders/custom-webpack:browser",
"options": {
...
- "baseHref": "./"
+ "baseHref": "./",
+ "customWebpackConfig": {
+ "path": "./webpack.config.js"
+ }
},
...
"builder": "@angular-builders/custom-webpack:browser" is necessary for the change to work - without it, the updated config will not even pass the syntax validation.
To check if everything is working as expected, let's visit <your-project-path>/dist/esbuild-loader-ng-cli/:

So let's compare the default build with the esbuild enhanced one. Unfortunately, the results are inconclusive - you get better speed or better build size (and less configuration headache), so you need to pick what is a priority for you.
As a baseline, let's use an example application as Angular CLI generated it. You can find the code in the main branch of the repo. My only change is that I tweaked the configuration to make the built code work from a subfolder - as describe here.
The build:
$ npm run build
> esbuild-loader-ng-cli@0.0.0 build
> ng build
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Size
main.03b0a30b1c3bb39428d7.js | main | 133.79 kB
polyfills.9a3c7adfe54759783845.js | polyfills | 35.99 kB
runtime.b557d7bc6f5a0a2b7c10.js | runtime | 1.02 kB
styles.31d6cfe0d16ae931b73c.css | styles | 0 bytes
| Initial Total | 170.81 kB
Build at: 2021-07-18T09:10:42.459Z - Hash: 02058db989498bb0ecd9 - Time: 11882ms
The key values:
The building code is available in the esbuild-loader-minimizer branch. Let's see how it performs:
$ npm run build
> esbuild-loader-ng-cli@0.0.0 build
> ng build
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Size
main.276f4eb0574e0396c077.js | main | 437.14 kB
polyfills.4a7829fed9a06cc470d3.js | polyfills | 39.22 kB
runtime.1d3895c9b4e2bbd6978f.js | runtime | 1.08 kB
styles.31d6cfe0d16ae931b73c.css | styles | 0 bytes
| Initial Total | 477.43 kB
Build at: 2021-07-18T09:31:40.831Z - Hash: 0a22501608de71af5712 - Time: 7657ms
The key values:
The build is faster, but unfortunately, the output file is much bigger &, as such, will be less optimal for our final users & transfer usage of our website. We have the same tread-off as in building with esbuild, but with less extreme values.