skip to content

Your build produces a 380 kB JavaScript bundle, but the browser reports about 110 kB transferred for that file. What accounts for the gap, and how many bytes does the browser actually have to parse and execute?

level: juniorimportance: must knowfreq 62%

answer

  1. two different sizes for one file
  2. the wire is not the engine
  3. decompress happens before parse
  4. saves network time, not CPU
  5. parse cost tracks the decoded size

basics

~20 s

The server compressed the response with gzip or Brotli, so only compressed bytes crossed the network. The browser decompresses first and then parses all 380 kB, so compression saves download time, not parse or execution cost.

solid answer

~40 s

The 110 kB is the compressed transfer size: the server sent the file with `Content-Encoding: gzip` or `br`, and text like JavaScript typically compresses to roughly a quarter to a third of its raw size. The browser decompresses the response before anything else touches it, so the JavaScript engine still sees all 380 kB — and that is the number that drives parse, compile and execute cost, and therefore main-thread blocking. Compression buys download time, which helps first paint and LCP on slow connections; it does nothing for Total Blocking Time or interaction latency. Both numbers matter, but for different problems: quote the compressed size when you are reasoning about network transfer, and the uncompressed size when you are reasoning about CPU. Only shipping less code moves the second one.

code

bash · 3 lines
bash
# Same URL, two sizes: compressed on the wire vs decoded for the engine
curl -sH 'Accept-Encoding: br' https://example.com/assets/app.js | wc -c
curl -s --compressed https://example.com/assets/app.js | wc -c

go deeper

for a junior

Be ready to say the transferred number is the compressed size while the resource size is what the engine parses, and that gzip or Brotli produced the gap — not minification.

for a middle

Explain the sequence out loud: the encoding is negotiated, the browser decompresses, and only then does parsing and compiling start. Know that minified text typically lands around a third of its raw size.

for a senior

Show the diagnostic instinct: when someone offers compression as the fix for a sluggish page, separate network-bound symptoms from main-thread-bound ones and name which metric each change can actually move.

for a principal

Own the convention: decide which size budgets, dashboards and library reviews quote, so teams cannot report shrinking compressed bytes while low-end devices keep paying the same CPU cost.

## Two sizes for one file Every text resource on the web has two sizes that people casually call "the size". The **transfer size** is how many bytes actually crossed the network — the compressed payload plus response headers. The **decoded (resource) size** is how many bytes exist after the browser undoes the compression, which is the file as your build wrote it. A 380 kB bundle showing 110 kB transferred is not a measurement error; it is the ordinary result of text compression, and a ratio near 3–4× is typical for minified JavaScript. ## How the compressed bytes get there The browser advertises the codings it accepts on the request, and a server that has a compressed form of the resource sends it back labelled with the coding it used: ```http GET /assets/app.8f3a1c.js Accept-Encoding: gzip, deflate, br HTTP/2 200 content-type: application/javascript content-encoding: br content-length: 112640 ``` Note what `Content-Length` counts here: the compressed body. Nothing in the response tells you the decoded size — the browser only learns it after decompressing. ## Why the decoded size is the one your CPU pays Decompression happens in the browser's network handling, before the resource is handed to the consumer that needs it. A JavaScript file is decompressed, then parsed, then compiled, then executed. A stylesheet is decompressed, then parsed into rules that the style engine matches against the DOM. In neither case does the compressed form reach the engine. So compression is a **transport** optimisation only: it changes how long the bytes take to arrive, not how much work the bytes cause once they have. Decompression itself is cheap relative to what follows — gzip and Brotli decode very fast, and for a few hundred kilobytes the decode is a small fraction of the parse-and-compile time on the same file, especially on a low-end phone where JavaScript parsing and compilation are the expensive part. ## Which metrics move, and which do not This distinction is the whole practical value of the question: - **Improved by compression:** anything gated on the resource *arriving* — TTFB is unaffected, but FCP and LCP improve when a render-blocking stylesheet or a script on the critical path arrives sooner, and the effect grows as connection bandwidth falls. On a fast connection the win can be nearly invisible. - **Not improved by compression:** anything gated on the main thread *working* — long tasks during startup, Total Blocking Time, interaction responsiveness. The engine does exactly the same amount of parsing, compiling and executing whether the file arrived compressed or not. That is why "we turned on Brotli and the score didn't move" is such a common story on script-heavy pages: the site was never network-bound in the first place. ## What actually reduces the decoded size Only changes to the code itself: minification (shorter identifiers, no whitespace — which also improves the compression ratio, since the two stack rather than substitute for each other), removing or replacing heavy dependencies, deleting unused code, and loading only what the first screen needs so the rest is parsed later or never. Note the sequence: minification shrinks what the engine parses, compression shrinks what the network carries, and they are not alternatives. ## Checking it yourself You can see both numbers directly by asking for the resource twice, once with a coding and once without: ```bash curl -sH 'Accept-Encoding: br' https://example.com/app.js | wc -c # wire bytes curl -s --compressed https://example.com/app.js | wc -c # decoded bytes ``` If the two numbers are identical, the response is not being compressed at all — a surprisingly common finding for assets served from a bucket or a second origin whose configuration nobody revisited. ## The habit to carry away When someone quotes a bundle size, ask which size. A library advertised as "12 kB gzipped" may be 40 kB of JavaScript that a phone must parse and compile every cold load. Budgets and dashboards should state the unit explicitly, because the compressed number is the right one for a network conversation and the wrong one for a CPU conversation.

  • If compression does not reduce parse cost, what does?
    Only shipping less code. Minification shrinks what the engine reads, dropping or replacing heavy dependencies removes it outright, and deferring code the first screen does not need moves the parse cost out of startup. Compression and caching change when and how fast bytes arrive; they never change how much work those bytes cause once decoded.
  • Is the decompression itself expensive on a low-end phone?
    Not meaningfully. Both gzip and Brotli decode far faster than a JavaScript engine parses and compiles the same content, so for a few hundred kilobytes the decode is a small share of the total cost. Brotli's asymmetry is on the encode side — high compression levels are expensive to produce, cheap to consume.
  • Why do libraries advertise a "gzipped size" if it hides the parse cost?
    Because it approximates what a user's connection has to carry, and it is comparable across libraries in a way raw size is not. It is a fair number for a network conversation and a misleading one for a CPU conversation, so a serious comparison quotes both — transfer bytes and the decoded bytes the main thread must process.

saying these in an interview costs you the question

  • Says compression reduces how much JavaScript the browser parses
  • Treats minification and compression as the same optimisation
  • Claims the browser executes the compressed bytes directly
  • Proposes better compression to fix a slow interaction
  • Quotes compressed size when reasoning about CPU cost

context