Building a Bundle Analyzer with V8 Coverage and Source Maps
Chuseok side quest, part 2: building a V8 coverage analyzer, one dead end after another.
Chuseok side quest, part 2: building a V8 coverage analyzer, one dead end after another.
Chuseok side quest, part 1: starting with my own blog
How much do you lose when 10MiB of functions you never call ships to the browser? I ran 855 measurements to separate the cost created by bytes from the cost created by the shape of the code. Uncalled declarations cost about 21ms per MiB and did not grow when I slowed the CPU by 4x, while initialization code that runs the moment the file is read added 201ms per MiB to the main thread. With real libraries, merely importing a module was enough to evaluate it.
I imported one constant and 97.7% of the bundle came along with it. The vendor had no timeline for a fix, so I pried open the published source maps, recovered over 400 TypeScript files, and rewrote the build, the entry points, and the dependencies however I wanted. Everything except the logic. That got /send to -77.5% raw. The hard part came after. All 1,932 tests passed, and a few of them were watching nothing at all.
In a Next.js 16 Turbopack production build, a module-scope singleton became two live instances at runtime. Inside the same synchronous block, one condition contradicted the other, and responses that arrived in 30ms still timed out. This is the record of tracing the cause through the bundle output: a partial scope hoisting merge, a circular import, an upstream bug that had already been fixed, and the single-variable experiment I ran too late.
The bundle costs that code review misses, and how to surface them in the PR.
Module boundaries created by a single line of 'use client', build-time transformations, Flight serialization, and performance implications
Thank you for your interest. 🙇🏻♂️
Thank you for your interest. 🎉