🔥 Battle for the Bundling time: esbuild — a JavaScript bundler and minifier written on Golang
Tags: go, node, javascript, news
Published: 2020-02-17 16:34:17

## Introduction

In this crazy world, it has become so _difficult_ to secure leadership in at least one discipline. And now, a new battle has already begun: the speed of assembly of bundle — a measure to determine **the best** JavaScript bundler... 

Hello, friend! And let the battle begins! ✊

### 📝 Table of contents

- [Bundlers versions](#ch-1)
- [Official benchmark results](#ch-2)
- [My own benchmark results](#ch-3)
  - [Rollup.js](#ch-3-1)
  - [Parcel](#ch-3-2)
  - [Webpack](#ch-3-3)
  - [esbuild](#ch-3-4)

<a name="ch-1"></a>
## Bundlers versions

Unfortunately, `esbuild` has no versions in repository, so I can't refer to a specific build of it. But, I'll use info from `package.json` file (17 Feb 2020):

```js
{
  "private": true,
  "devDependencies": {
    "js-yaml": "3.13.1",
    "parcel": "1.12.4",              // -> latest 1.x version
    "rollup": "1.20.3",              // -> not latest version
    "rollup-plugin-terser": "5.1.3", // -> not latest version
    "webpack": "4.39.3",             // -> not latest version
    "webpack-cli": "3.3.7"
  }
}
```

<a name="ch-2"></a>
## Official benchmark results

> [...] benchmark approximates a large codebase by duplicating the [three.js](https://github.com/mrdoob/three.js) library 10 times and building a single bundle from scratch, without any caches. [...] esbuild is **10-100x faster** than the other JavaScript bundlers I tested (webpack, rollup, and parcel) [...]

Authors run benchmark on 6-core **2019 MacBook Pro** with 16gb of RAM. This table show official results from [README](https://github.com/evanw/esbuild/blob/master/README.md):

| Bundler         |    Time | Relative slowdown | Absolute speed | Output size |
| :-------------- | ------: | ----------------: | -------------: | ----------: |
| esbuild         |   0.58s |                1x |    1028 kloc/s |      5.83mb |
| rollup + terser |  43.56s |               75x |      14 kloc/s |      5.96mb |
| webpack         |  47.85s |               83x |      12 kloc/s |      5.82mb |
| parcel          | 120.45s |              208x |       5 kloc/s |      5.90mb |

Impressive, isn't it? Yeah, me too. But I was taught **not to believe** the word numbers on the Internet (_especially when it comes about JavaScript_).

<a name="ch-3"></a>
## My own benchmark results

So, I decided to double-check everything on my work computer: 4-core **2015 MacBook Pro** with 8gb of RAM.

![my macbook](https://dev-to-uploads.s3.amazonaws.com/i/fyls2phv9qpji57wl1u1.png)

OK! Let's `git clone` and run `make bench-three` from root folder:

```console
$ git clone https://github.com/evanw/esbuild.git
$ cd esbuild
$ make bench-three
```

<a name="ch-3-1"></a>
### Rollup.js

> [...] used the `rollup-plugin-terser` plugin because rollup itself doesn't support minification.

```console
Done in 1m 15.2s

real 77.02
user 87.98
sys 6.04

5.8M    bench/three/rollup/entry.rollup.js
 19M    bench/three/rollup/entry.rollup.js.map
```

Hmm... 🤔 it was a strange result! IDK what's wrong, because I saw this result (±10s) **each time** on my MacBook Pro. But, okay. Let's see next bundler.

<a name="ch-3-2"></a>
### Parcel

> [...] Parcel uses the default options.

```console
Done in 322.5s

real 323.92
user 387.59
sys 33.24

6.8M    bench/three/parcel/entry.parcel.js
 20M    bench/three/parcel/entry.parcel.js.map
```

I often use **Parcel** on small projects without _React.js_ or other frameworks. I know that it's _not fastest_, so this result didn't surprise me much.

<a name="ch-3-3"></a>
### Webpack

> [...] Webpack uses `--mode=production --devtool=sourcemap`. 

```console
Done in 81.3s

real 82.81
user 100.26
sys 5.69

6.0M    bench/three/webpack/entry.webpack.js
 19M    bench/three/webpack/entry.webpack.js.map
```

Perhaps this is the most interesting result (for me) of _the Big three bundlers_! I'd never have thought, that _Webpack_ could do this job **better** than _Rollup_... 🤯

<a name="ch-3-4"></a>
### esbuild

> [...] running esbuild with `--bundle --minify --sourcemap`.

```console
Done in 1.4s

real 1.47
user 3.14
sys 0.61

5.8M    bench/three/esbuild/entry.esbuild.js
 17M    bench/three/esbuild/entry.esbuild.js.map
```

Yeah, I'm shocked, too. How can that be? Actually, it's simple **Go** magic! ✨

> - It's written in Go, a language that compiles to native code
> - Parsing, printing, and source map generation are all fully parallelized
> - Everything is done in very few passes without expensive data transformations
> - Code is written with speed in mind, and tries to avoid unnecessary allocations

## Photo by

[Title] esbuild authors https://github.com/evanw/esbuild
[1] Vic Shóstak (article author)

<a name=""></a>
## P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv