Build1 distinct publisher2 min readPublished
A Capacitor puzzle build now delivers 5.88 MB where it once delivered 13.09 MB, yet the bundle on disk barely moved, because R8 writes a 3.83 MB deobfuscation map that Play keeps and never sends to a phone.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The measurement is three filters over `unzip -lv` output: take the compressed column rather than the uncompressed one, drop every path under `BUNDLE-METADATA/` and `META-INF/`, and drop entries tagged with any screen density other than the one you asked for, which defaults to xxhdpi [7][8]. That models two of the three splits the author says Play performs, since he lists density, ABI and language [4]. Only density is implemented in the code as published [7]. A Capacitor app carries almost no native code, so the hole costs nothing here. Run the same script over a bundle with four ABIs of `.so` files, or fifty locales of resources, and it reads high, in a direction you can predict and a magnitude you cannot know until you open the zip.
Then the arithmetic. The after run reports 10.41 MB on disk against 5.88 MB delivered [10], a gap of 4.53 MB, and the mapping file alone is 85% of that gap [2][3][5]. The before run's gap was 3.74 MB [5] with no mapping file in the archive, which on the article's own accounting leaves the signature block plus the other density buckets. So the file you can `ls` shrank 38% while the download shrank 55% [4][1]. The map arrives at the exact moment you enable the thing that halves delivery, which is an efficient way to get a config change reverted at review.
The share table is the other useful result. After the pass the two remaining dex entries are 3.21 MB and 1.03 MB [13], which is 4.24 MB, still 72% of the download [6] and effectively the share dex already held [12]. R8 deleted 5.31 MB of dex [7] and left the composition where it was. Content moved the other way: 1.65 MB down to 1.10 MB in bytes [11][13], but 12.6% up to 18.7% as a share [8]. The stated figure of 16% for content [2] only reconciles if the 0.35 MB drawable line counts as content too, since 2.00 MB of 13.09 MB is 15.3% [9]. Worth knowing which definition your own size budget uses.
For the halving to transfer, the baseline has to still be the unminified default that Capacitor generates, with a dependency tree big enough that the shrinker has something to delete [14], and dex has to dominate your delivered split the way it does here [12]. If R8 is already on, the 7.21 MB [1] is not sitting there waiting for you. The author is explicit that his number is an estimate rather than bundletool's figure, and that its value is moving when the real one moves [15].
Ranked by verification strength, evidence, and original report placement.
The author states that content was 16% of the download and the Android runtime was most of the rest.
The release buildType that npx cap add android generates sets minifyEnabled false, so nothing shrinks and every class of Play Services, Firebase, gRPC and Guava ships whole.
The app under discussion is a word puzzle with 392 levels of JSON that shipped as a 17 MB App Bundle, which the author initially assumed was the levels' fault.
After the optimisation pass, a phone downloads 5.88 MB where it used to download 13.09 MB.
The size of the .aab on disk is not the download: Play splits a bundle per device by screen density, by ABI and by language, and strips its own metadata before delivery.
Turning on R8 adds a BUNDLE-METADATA/.../proguard.map to the .aab, 3.83 MB on this app, which Play keeps to deobfuscate crash reports and never sends to anyone.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · September 2, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
The laptop the agent replaced was a CI runner: an Android release driven from a phone browser1 distinct publisher
build
Split Flutter CI from CD, or pay macOS rates on every pull request1 distinct publisher
build
An Android rebrand is two jobs, and only one of them is cheap1 distinct publisher
build
Android's September 30 verification cutoff reaches the staging flavor on your tester's phone1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One builder's own numbers, reproducible by anyone
Everything rests on a single developer's build, published on dev.to: two runs of a script he wrote, pasted as text. What lifts it above anecdote is that the mechanism is verifiable in a minute by anyone with unzip and a bundle, and the script is printed whole rather than described. What holds it down: the author himself calls the output an estimate rather than bundletool's figure, the prose's 15.5 MB never reconciles with the 10.41 MB the output prints, and the text stops mid-Gradle so part of the config that produced the win is off the page.
One app, one developer, one Play listing
The puzzle game really is going out through Play — that is why density splitting and the retained mapping file matter at all — so this is a shipped change rather than a lab exercise. But it is exactly one shipped change. Nobody else in this reporting has run the script, audited the Capacitor default they inherited, or reported a second set of before-and-after numbers.
Credit skewed toward R8
The framing hands the halving to R8, and the source's own footnote is more careful about it: turning R8 on took the download from 13.09 MB to 7.76 MB, with resource exclusions and the rest of the pass closing the remaining distance to 5.88 MB. The 3.83 MB map is exactly as described and the phantom-improvement trap is real; it is the attribution that runs slightly ahead of the arithmetic.
Series audience, no vendor to sell
This is instalment nine of ten, funnelling readers from dev.to back to indiecore.net, so there is an audience being assembled and a reason to make the numbers sound decisive. Against that: no product or SDK is being pitched, the script is given away in full, and the finding cuts against the author's own opening assumption that his level data was the problem — self-correction is a weak commercial motive.
Reproducible method, unreplicated numbers
Confidence tracks the shape of the sourcing: one first-party account, internally coherent except for a single stray size figure, describing behaviour any Android developer can confirm against their own bundle. Nobody outside dev.to has touched the claim, and the truncated build file means the reproduction would not be exact.