minification-benchmarks: measuring the JavaScript minifiers against each other
🏃♂️🏃♀️🏃 JS minification benchmarks: babel-minify, esbuild, terser, uglify-js, swc, google closure compiler, tdewolff/minify, oxc-minify
At a glance
- What is it?
- This repository answers the question every bundler user eventually asks, which minifier should I use, by running twelve of them in separate processes over the same input, verifying that the output still works, and reporting three numbers per tool, the minified size, the gzipped size and the time. The headline is a weighted score, and the README is careful to tell you to read the columns rather than the ranking.
- Who is it for?
- Adopt this benchmark when you are choosing a minifier, because it measures the thing you actually ship, the gzipped size, and it checks that each minifier's output still works rather than trusting the tool. Do not adopt its ranking as a default for your project, since the score weights size over time by 85 to 15 and the README tells you to read the individual columns if speed matters more.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The question, and the three stated reasons for answering it
The README opens with a single question, what's the best JavaScript minifier, and then gives three reasons the project exists. To help you pick a minifier that fits your needs. To promote JavaScript minifiers and document their performances. And to encourage healthy competition and improvement amongst minifiers.
The third reason is the one that explains the shape of the project. A benchmark that only reported a winner would end the conversation; a benchmark that keeps the tool maintainers visible, with their release dates in a table, keeps them improving. The table of minifiers is therefore part of the argument, and it is regenerated as part of the README rather than maintained by hand.
The list is broad and current. It covers bun, oxc-minify, @swc/core, terser, esbuild, google-closure-compiler, @tdewolff/minify, @cminify/cminify-linux-x64, uglify-js, babel-minify and tedivm/jshrink. The versions and release dates are in the table, from bun at 1.4.3 released on 2026-10-10, through oxc-minify at 0.153.0 and @swc/core at 1.16.13, down to babel-minify at 0.5.2 from May 2022 and jshrink with no release date at all.
That spread of dates is itself information. The tools that are actively developed are the ones at the top of the table, and a benchmark that lists a minifier whose last release was in 2022 is telling you something about its future.
Separate processes, an integrity check, and a ten second timeout
The methodology section is short, and each item removes a way the numbers could lie.
Each minifier is executed in its own process with a ten second timeout. The separate process matters because a minifier that crashes must not take the harness with it, and the timeout matters because a minifier that hangs would otherwise hang the run.
Artifact integrity is verified by a test before and after minification. So the harness runs the input, checks it still behaves, minifies it, and checks again. A minifier that silently breaks the code is caught rather than being credited with a good size number.
Each minifier is minimally configured, with sourcemaps and comments disabled, comparing the out-of-the-box experience. That is a deliberate choice to measure what a user gets by default rather than what a tuned configuration can achieve, and it is the choice that makes the comparison fair across tools with very different option surfaces.
The automation closes the loop. Minifier upgrade pull requests are handled by WhiteSource Renovate, so tracking a new release of a tool is a routine pull request rather than a research project, and the benchmarks themselves are updated on every pull request through GitHub Actions. The raw data is published at packages/data/data/data.json, which means the chart in the README is a rendering of a file you can read.
The benchmarks were last updated on Oct 10, 2026.
Three columns, and the one that matches what you ship
The metrics section defines three numbers per minifier.
Minified size is simply the size of the minified output. Minzipped size is the size of the minified output with Gzip compression, and the README splits that into two readings. For minifiers, it measures how compressable the output is. For users, it measures network transfer size, which is usually the metric that matters most.
That distinction is the most useful sentence in the document. A minifier that produces slightly larger output can still be the better choice if that output compresses better, and the reverse is also true. Judging on raw size alone rewards whichever tool happens to emit a shape that gzip likes, rather than whichever tool removes more information.
Time is the third column, defined as how long minification took, averaged over five runs. Each time is annotated with a multiplier relative to the fastest minifier, which is a better presentation than absolute milliseconds when the difference between the fastest and the slowest is a factor of fifty.
For a user, the gzipped column is the one that maps to the user experience, since that is the bytes crossing the network. For a build pipeline that runs on every commit, the time column decides whether minification becomes a bottleneck in continuous integration.
The composite score, and the weighting that decides it
For each benchmark, the minifiers are ranked by a score that reflects the best balance of trade-offs, and the README describes exactly how that score is built.
The score combines minzipped size and minification time, with size weighted more heavily by default, 85 percent size and 15 percent time, since it is usually the top priority. If a minifier is unusually slow, the weights shift toward time using a logistic sigmoid function, up to a 50/50 split. The stated reason for the sigmoid is that this avoids harsh cutoffs while still penalising extreme slowness.
Both size and time are scaled using min-max normalisation so they can be compared fairly, and the result is described as a context-aware score that helps surface the best overall choice. Then comes the caveat that matters: make sure to check each column directly if size or speed matters more to you.
This is a well-designed scoring function, and the caveat is not a formality. A single number necessarily hides the trade-off, and the two weights are not equally right for everyone. A library published to npm and consumed by bundlers cares about the gzipped size, since that is what users download. A monorepo that minifies hundreds of packages on every commit cares about time, and for that team the ranking order in the README is close to meaningless.
The sigmoid is the interesting detail. A hard cutoff, where anything slower than a threshold loses outright, produces a cliff that a small change in the input flips. A smooth function means a tool that is nearly as fast still scores well, and only a genuinely pathological case is pushed towards the time half of the weighting.
What the current numbers say
The results section embeds a chart, and the data behind it is readable in the source of that chart, which is the gzipped size for a set of minifiers against the original.
The original input compresses to 19385 bytes. The tools land close together at the top: uglify-js at 8177, @swc/core at 8186, google-closure-compiler at 8216, terser at 8255, oxc-minify at 8354, bun at 8516, esbuild at 8542, @tdewolff/minify at 8628. The two no-compress variants sit higher, with uglify-js without compress at 8668 and terser without compress at 8739, and the two outliers are @cminify/cminify-linux-x64 at 10858 and tedivm/jshrink at 11040.
Two things are worth reading off that list. The spread between the best and the worst of the mainstream tools is about 5 percent, which is small enough that the choice matters less than the configuration, and the difference between a minifier with compression and one without is comparable to the difference between two different minifiers, which says compression is the bigger lever than the tool.
That is the argument for reading the columns. The gap between the leaders is narrower than the gap between compressed and uncompressed output, so a team that leaves compression off is leaving more on the table than it would gain by switching minifiers.
Where a benchmark is the wrong instrument
The first limitation is that the input is not your code. A benchmark measures a fixed corpus, and the ranking is a statement about that corpus. A library with long repeated identifiers and a bundle with many unique string literals will rank differently, because the compressibility of the input decides how much the minifier choice matters at all.
The second is that the configuration is deliberately minimal. Sourcemaps and comments are off, and nothing else is tuned. Some minifiers have options that materially change their output size, so a team that would enable those options is looking at a different result from the table.
The third is that the comparison is a snapshot. The table is generated on every pull request, so it is current for the tool versions listed, and it will be wrong the moment a new release lands. The version table is therefore part of the result, and reading a size number without checking which version produced it is how people end up quoting stale figures.
The fourth is that a benchmark cannot tell you whether a minifier's output is safe for your code beyond the integrity test the harness runs, which is a functional check and not a security analysis. If you enable aggressive transformations, the settings you choose matter more than the tool you chose.
MIT, a pnpm workspace, and benchmarks that update themselves
The project is MIT licensed, with the LICENSE file at the repository root, and the package metadata names the author as Hiroki Osame. The default branch is master, the repository is not archived, and the last push was on 2026-10-13, which is three days after the benchmark date the README reports.
The repository is a pnpm workspace with the package manager pinned at pnpm 10.17.0, and the root package is private with an empty files array, so nothing here is published as a library. The workspace packages are visible in the dev dependencies as workspace references, an artifacts package, a minifiers package that holds the tool definitions, a utils package, and a data package, alongside the bench package that the scripts call into.
The scripts are the operational surface. The bench script runs the benchmark CLI, bench-all runs the full sweep, the test script runs the test suite in packages/bench/tests, update-readme regenerates the README with the current data, and it uses --env-file-if-exists so it works whether or not an environment file is present. Linting uses lintroll with an ignore pattern for the raw data file, and type checking is plain tsc.
The one unusual thing in the root package is the prepare script, which runs skills-npm with an agents flag. That installs agent instructions into the repository as part of install, which tells you something about how the project expects to be worked on.
For an adopter, the whole loop is designed to need no maintenance from them, and the only real decision left is which column of the table you trust.
Editorial conclusion
Adopt this benchmark when you are choosing a minifier, because it measures the thing you actually ship, the gzipped size, and it checks that each minifier's output still works rather than trusting the tool. Do not adopt its ranking as a default for your project, since the score weights size over time by 85 to 15 and the README tells you to read the individual columns if speed matters more. Before you decide, look at your own bundle, because the ranking is a comparison across a fixed set of inputs, and check the version table, since each minifier is pinned and the newest release in the list is from October 2026.
Frequently asked questions
What does the minification-benchmarks project compare?
It benchmarks twelve JavaScript minifiers, including bun, oxc-minify, @swc/core, terser, esbuild, google-closure-compiler, @tdewolff/minify, @cminify/cminify-linux-x64, uglify-js, babel-minify and tedivm/jshrink, reporting minified size, gzipped size and minification time for each.
How are the minification benchmarks run?
Each minifier is executed in its own process with a ten second timeout, artifact integrity is verified by a test before and after minification, and each is minimally configured with sourcemaps and comments disabled to compare the out-of-the-box experience. The raw data is published in the repository.
How is the ranking score calculated?
The score combines minzipped size and minification time, weighted 85 percent size and 15 percent time by default, and if a minifier is unusually slow the weights shift toward time using a logistic sigmoid up to a 50/50 split. Both values are min-max normalised, and the README advises checking the individual columns if size or speed matters more to you.
Which metric matters most for a website?
The gzipped size. The README explains that for minifiers it measures how compressable the output is, and for users it measures network transfer size, which is usually the metric that matters most.
How do I run the benchmarks myself?
The repository is a pnpm workspace with the package manager pinned at pnpm 10.17.0. The scripts include bench, which runs the benchmark CLI, bench-all for the full sweep, and a test script, and update-readme regenerates the README from the current data.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/privatenumber-minification-benchmarks)Was this useful?