Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESbuild lags behind (non-trivially) in producing gzip friendly output for large pacakges #10

Closed
pastelsky opened this issue Apr 4, 2021 · 8 comments

Comments

@pastelsky
Copy link

pastelsky commented Apr 4, 2021

Thanks for publishing these benchmarks. I'm the author of bundlephobia (a tool developers use to find out minified and minzipped sizes of npm packages) and was contemplating on replacing Terser with ESBuild's minifier to shave a few seconds from build.

Seeing this benchmark, I got the picture that ESBuild and Terser and neck to neck. However, this doesn't seem to be the case for large packages. While the minified size might still be comparable in some cases, the gzipped size difference between esbuild and terser can vary between 5%-9% — which one might consider non-trivial difference for minification.

Benchmarks after replacing Terser with ESBuild in Bundlephobia's webpack config, and after manually extracting out license-style comments —

Package Minified Terser Minified ESBuild Minzip Terser Minzip ESBuild
webpack 2.48 MB 2.52 MB (+2%) 650KB 683 KB (+5%)
echarts 957 KB 975 KB (+2%) 304KB 316 KB (+4%)
antd 1.16 MB 1.27MB (+9%) 345 KB 370 KB (+7%)
victory (charts) 518 KB 532 KB (+3%) 130KB 140 KB (+8%)

The results remain the same whether running esbuild minify through esbuild-loader or the ESBuild CLI on the webpack built bundle.

Is there anyway to capture this on the current page?

@privatenumber
Copy link
Owner

privatenumber commented Apr 5, 2021

Thanks @pastelsky -- I love Bundlephobia! Thanks for you work on that :)

Sounds like what you're referring to is the "compressability" of the minified output, which I have a bullet-point for under "Methodology". This isn't a metric often looked at when evaluating a minifier but I agree it's an important factor in comparing minifiers.

There will always be a performance discrepancy across minifiers as long as they use different optimizations. By how much depends on the input code. eg. you can exaggerate the performance difference between Terser and esbuild by using more patterns that esbuild does not minify but Terser does.

Sorry if the communication mislead you -- I will update the README to make it clear that esbuild is not a drop-in replacement for Terser.

If you're looking for a faster Terser replacement for Bundlephobia, definitely subscribe to swc-project/swc#1302 where the author of SWC and Terser are collaborating on a Rust implementation. Last I checked, esbuild doesn't have any more plans to improve minification.

I think the best a benchmark can do to highlight the differences is by adding more larger data samples. Feel free to open PRs to add more, or list them here and I will add them when I find time. They should be single-file though, so Webpack won't work, but these from your list will work:

@kzc
Copy link

kzc commented Apr 10, 2021

https://unpkg.com/[email protected]/dist/victory.js is rather odd. Every bundled module is an eval'ed string block of webpack requires:

/******/ ({

/***/ "../../../node_modules/d3-array/src/array.js":
/*!******************************************************************************!*\
  !*** /Users/boygirl/formidable/v/victory/node_modules/d3-array/src/array.js ***!
  \******************************************************************************/
/*! exports provided: slice, map */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"slice\", function() { return slice; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"map\", function() { return map; });\nvar array = Array.prototype;\n\nvar slice = array.slice;\nvar map = array.map;\n\n\n//# sourceURL=webpack://Victory//Users/boygirl/formidable/v/victory/node_modules/d3-array/src/array.js?");

/***/ }),

Perhaps it was produced with webpack's debug or development mode. While it can be (poorly) minified, I don't think it is representative of how typical production libraries or applications are bundled and probably should not be included in the benchmark.

@privatenumber
Copy link
Owner

Good catch @kzc ! Reported in FormidableLabs/victory#1818

@privatenumber
Copy link
Owner

No more evals in victory: https://unpkg.com/[email protected]/dist/victory.js

@privatenumber
Copy link
Owner

FYI I updated it to include antd, echarts, victory.

It might be because I upgraded esbuild to the latest, but the performance difference between esbuild and Terser seems a lot smaller now (2% at most minzipped).

I will close this when I update the README to mention that esbuild is not a drop in replacement for Terser.

@kzc
Copy link

kzc commented Jun 5, 2021

Since we're on the topic of bundle sizes, the google-closure-compiler.advanced minified commonjs files do not work correctly. Without test programs to verify the correctness of the minified bundles, the benchmark results have to be taken with a grain of salt.

@privatenumber
Copy link
Owner

privatenumber commented Jun 5, 2021

Thanks @kzc, it's on my radar.

Looking to knock out some of these easier issues first.

@privatenumber
Copy link
Owner

Closed via 5aac6e5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants