awesome-everything RU
↑ Back to the climb

Performance

What a bundle actually costs: download, parse, compile, execute

Crux A 1 MB JS bundle is not a 1 MB cost — it is four chained CPU phases that hit mid-range mobile 4-8x harder than your laptop.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at junior altitude — the surface
◷ 12 min

A developer ships a new feature on a Friday. On their MacBook the page loads in 800 ms — feels fine. By Monday, bounce rate is up 20%. A colleague tests on a mid-range Android phone and watches the page sit blank for 8 seconds. The feature was fine. The bundle was not.

Four phases, one cost

When a browser downloads a JavaScript file, it does not just “load” the code. It runs four sequential phases before a single user interaction is possible.

Download — the bytes travel over the network. On a 4G connection, 200 KB gzip’d takes 150-500 ms depending on signal quality.

Parse — the JS engine walks every byte and builds an abstract syntax tree (AST). V8 parses at roughly 1-2 MB/sec on a fast laptop CPU, but only 200-400 KB/sec on a median Android device. A 500 KB uncompressed bundle takes about 1.5-2 seconds to parse on mid-range mobile.

Compile — the engine converts the AST to bytecode, then to optimised machine code. V8 uses a tiered pipeline (Ignition → Sparkplug → TurboFan). Compile cost grows roughly linearly with how much code actually runs at startup.

Execute — the bundle’s top-level code runs synchronously: framework initialisation, store creation, route registration. For a typical React + Redux app this blocks the main thread for 100-500 ms.

The full chain on mid-range mobile for a 500 KB uncompressed bundle: download 800 ms + parse 1.5 s + compile 300 ms + execute 400 ms = roughly 3 seconds before the user can click anything. Each phase is a separate lever; none of them helps unless you address it directly.

PhaseBottleneckMid-range mobile cost (500 KB uncompressed)
DownloadNetwork bandwidth~800 ms on 4G
ParseCPU — V8 walks every byte~1.5-2 s
CompileCPU — JIT tiers~300 ms
ExecuteCPU — single-threaded startup~400 ms

Why “works on my laptop” fails

A developer’s MacBook M-series has a single-thread CPU speed roughly 4-8x faster than a median Android phone (Snapdragon 6 or 7-series equivalent). A 5G or Wi-Fi connection helps with download — but parse, compile, and execute happen entirely on the user’s CPU. Faster network does not move that needle at all.

Most users in global markets are on mid-range or older hardware. Teams that test only on flagship phones or development machines systematically underestimate real-user experience. Chrome DevTools has a 4x CPU throttling mode that approximates mid-range Android; using it for every performance check catches the gap before it reaches production.

The bundle-budget discipline

A bundle budget is a maximum number of bytes (typically gzip’d JS, CSS, images split separately) that a route is allowed to ship, enforced at CI time. Without a budget, bundle size grows by accretion: each engineer adds a library, each library adds a few KB, no single PR is to blame, but after six months the bundle has doubled. With a budget, every PR that pushes past the cap fails CI — the team either justifies the addition or finds a smaller alternative.

The budget converts performance from an intention into a constraint. It does for client-side bytes what an SLO does for server-side latency: makes it measurable, enforced, and owned.

Why this works

Why does a 1 MB JS bundle cost more than a 1 MB image? An image is downloaded, decoded by the GPU, and painted. JS is downloaded, then parsed, compiled, and executed on the CPU — three extra phases that are slow, sequential, and block the main thread. Per byte, JS is roughly 5-10x more expensive than an image on mid-range mobile.

Quiz

A 500 KB uncompressed JS bundle loads fine in 400 ms on a dev laptop. Estimate the likely Time to Interactive on a mid-range Android on 4G.

Order the steps

Order the JS bundle lifecycle from network request to first user interaction:

  1. 1 Browser requests the JS file from the server
  2. 2 Server returns the file (often gzip or brotli compressed)
  3. 3 Browser decompresses and receives bytes
  4. 4 JS engine parses bytes into an abstract syntax tree (AST)
  5. 5 JS engine compiles the AST into bytecode and then optimised machine code
  6. 6 Browser executes top-level code: imports, side effects, framework init
  7. 7 App reaches interactive state — user can click
Quiz

A team switches from gzip to brotli compression and the bundle goes from 180 KB to 150 KB transferred. LCP improves by 50 ms. Is the bundle problem solved?

Recall before you leave
  1. 01
    Name the four phases a JS bundle goes through before a page is interactive.
  2. 02
    Why does a 4G upgrade not fix parse and compile times?
  3. 03
    What is a bundle budget and what does it prevent?
Recap

A JavaScript bundle triggers four sequential CPU phases: download, parse, compile, execute. The first is network-bound; the other three are CPU-bound and run 4-8x slower on a median Android than on a dev laptop. A 500 KB uncompressed bundle can cost 3 seconds of blocked main thread on mid-range mobile — invisible in development. Bundle budgets make the cost a per-route constraint enforced at CI, catching drift before it reaches users. The next lesson connects these costs to Google’s Core Web Vitals and the concrete thresholds that define “good” vs “poor” for LCP, INP, and CLS.

Connected lessons
appears again in159
Continue the climb ↑Core Web Vitals: LCP, INP, and CLS
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.