evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.23k stars 1.16k forks source link

Showing gzip sizes in the bundle analyzer #3237

Open fabiospampinato opened 1 year ago

fabiospampinato commented 1 year ago

I've kinda replaced bundlephobia with esbuild's bundle analyzer personally, but one thing I miss from bundlephobia is seeing the min+gzip size, which doesn't seem available in esbuild's bundle analyzer.

I'm thinking the gzip size for each file can be listed fairly naturally in the modal that is opened on click.

For the entire bundle it seems trickier UI-wise, maybe there could be a button that toggles between min and min+gzip sizes, both in the header, in tooltips, and in the size used to render the chart itself.

evanw commented 1 year ago

How would this work? When you gzip a bundle, gzip deduplicates strings across modules for compression. So you can't accurately report a gzip size for a single module in a bundle because it's all compressed together. It's not the case that compressing each file individually adds up to the compressed size for the final bundle.

For example:

$ node -e 'console.log("x".repeat(1000))' > a.js    
$ node -e 'console.log("x".repeat(1000))' > b.js
$ echo 'import "./a"; import "./b"' | esbuild --bundle --minify | gzip -9 | wc -c
50
$ echo 'import "./a"' | esbuild --bundle --minify | gzip -9 | wc -c
41
$ cat a.js | gzip -9 | wc -c
30

Showing the gzipped size of a.js as 30 bytes doesn't make sense. Removing a.js from the bundle would only remove 9 bytes, not 30. Also visualizing the size of a.js and b.js as both being 30 bytes doesn't make sense for the visualization because the whole bundle is only 50 bytes, which is smaller than 30 + 30 = 60.

You could have the visualization invent some number by calling the gzip algorithm on something. But it seems misleading to do that, and I don't want the visualization to be misleading.

fabiospampinato commented 1 year ago

Right 🤔 These measurements are kinda fundamentally fuzzy imo, like we can't even say for sure that the server will compress at level 9, or which algorithm it will use (they are experimenting with adding support for zstandard to browsers I think, and as I understand it different gzip implementations could produce somewhat different results, like the size of each compressed block is basically arbitrary).

The global gzip size for the entire bundle, arbitrarily measured at level 9, is imo the main number that people want to see from tools like Bundlephobia and BundleJS, so it seems natural for esbuild's bundle analyzer to show that too, by compressing each output file individually and adding up the numbers, which should be very accurate.

The local gzip size for each individual file is indeed somewhat nonsensical, and it can just be ignored and it wouldn't matter much I think, though iirc tools like webpack-bundle-analyzer or rollup-plugin-visualizer have it, and it's somewhat interesting, because not all modules have very close compression ratios, like udhr gets ~80% smaller, but cdl3-asm gets ~50% smaller, when one renders the chart using these somewhat made-up gzip sizes some modules end-up getting noticeably bigger, it's almost a way to highlight portions of the bundle by how expensive they will be to download rather than parse. If the numbers are not spot on the chart can still be interesting. But I can understand if something like this isn't "perfect" enough for esbuild.