Quick answer: minification removes what browsers don't need — comments, whitespace, and (with mangling) long variable names — without changing what the code does. Percent saved = (input − output) ÷ input × 100. On our 823-byte cart-totals sample, Terser strips it to 651 B (20.9% saved), compresses to 598 B (27.3%), and compress+mangle reaches 390 B (52.6% saved, 277 B gzipped). All three passes compute the identical $74.68 cart total. Everything runs locally; no code is uploaded.

Your JavaScript

Ad
Input
—
Output
—
Saved
—
Gzip in → out
—
—
Ad

What Each Terser Pass Buys You

PassWhat it removes823-B sample →Saved
Strip onlyComments, indentation, newlines651 B172 B (20.9%)
Compress…plus dead branches, constant folding, joined declarations598 B225 B (27.3%)
Compress + mangle…plus 1–2 character names, inline helpers (TAX_RATE → t)390 B433 B (52.6%)
Same file, gzippedTransport compression on top of the smallest pass277 B29.5% off the 393-B gzip

Every row was measured with Terser 5.51.2 — the exact browser bundle this page loads — on the sample behind the Sample button. Your mileage depends on your comment density and name lengths: a heavily commented file shrinks more; a machine-generated bundle shrinks less.

How the JS Minifier Works

This tool is a thin, honest wrapper around Terser 5.51.2 (BSD-2-Clause), the minifier that webpack, Vite, and Parcel lean on in production builds. It loads the official Terser browser bundle on first use and runs it in your tab. No server sees your code, which makes it usable for quick one-off shrinks, snippets heading into CMS blocks, or checking what a bundler pass would buy you.

The math

Bytes saved = input − output. Savings percent = (input − output) ÷ input × 100. The tool counts UTF-8 bytes (not characters) so multi-byte strings report honestly, and when your browser supports CompressionStream it also shows gzip sizes for both sides — the number that actually crosses the network.

How to use it

Paste code (or hit Sample), pick a preset, and results update as you type. The page opens on Compress + mangle, the smallest output. Strip only is the safest choice for code you'll still need to debug from stack traces: line breaks go but nothing is renamed or rewritten. Compress rewrites the logic to shorter equivalents. Compress + mangle also renames top-level names — smallest output, but other scripts can no longer call your globals by name, and Function.prototype.name changes.

A worked example

The Sample button loads an 823-byte cart-totals script: a tax constant, a money formatter, a per-line discount helper, and a cartTotal() that returns subtotal, tax, and total. Run each preset and the output column walks down 651 → 598 → 390 bytes. We verified all three outputs in Node against the same bundle: each one computes {subtotal: "$68.99", tax: "$5.69", total: "$74.68", itemCount: 2} from a two-item cart — identical answers, 52.6% of the bytes gone at the strongest pass, and 277 B once gzipped.

One caution worth repeating: minification is not obfuscation. Anyone can pretty-print 390 bytes back to readable form in seconds. If the goal is deterring reverse engineering rather than shipping smaller files, that's a different tool. Our JS Obfuscator covers it, and the guide to JavaScript obfuscation explains what it can and can't protect.

What Each Preset Does to Real Code

We ran six small snippets through Terser 5.51.2 with the exact options behind each preset. The results show where the savings come from, and where the strongest preset can surprise you.

InputStrip onlyCompressCompress + mangle
const SECONDS = 60 * 60 * 24; used in an exported functionKept as 60*60*24Folded to 86400 and inlinedexport function days(n){return 86400*n}
const DEBUG = false; guarding a console.logKeptThe log call is removed as dead codeEverything removed (nothing is used)
A wrapped helper that always returns 10Same code, no spaceswindow.result=10;window.result=10;
var config = {theme:'dark'} read by init()Names keptNames keptvar a="dark";document.body.className=a;
function handleClick(){...} called from an HTML onclickKeptKeptRemoved entirely (output is empty)
/*! MyLib v1.2 | MIT */ license headerRemovedRemovedKept

Compress does the clever work: constant folding, dead-code removal and inlining. Mangle adds the short names. The big caveat sits in the last two rows of behavior, which we explain next.

Why Is My Minified Output Empty or Broken?

The Compress + mangle preset runs Terser with its top-level option switched on. That tells Terser your file is self-contained: nothing outside it will ever call its functions or read its variables. Under that assumption, a function nobody inside the file calls is dead code, so it's deleted. Top-level variables get renamed, too.

That's exactly right for a bundle or an ES module. It breaks classic scripts that other code depends on. If your HTML has onclick="handleClick()", or another script reads a global like config, the minified file no longer provides it. In our test, a file holding only an onclick handler and one variable came out completely empty.

You've got three fixes:

Syntax errors are a separate case. Terser refuses to minify code it can't parse and shows its own message, such as Unexpected token: punc (;). Fix the line it points at and the output reappears as you type.

Does Minifying Keep License Comments?

Only on the strongest preset. Strip only and Compress run with all comments switched off, so every comment goes, license headers included. Compress + mangle uses Terser's default, which keeps comments that start with /*! or contain @license or @preserve.

That matters if you're shipping open-source code. MIT, BSD and similar licenses ask you to keep the copyright notice with copies of the software. If you use the lighter presets on a third-party library, paste its license header back at the top of the output.

How Much Does Gzip Change the Picture?

A lot. Servers and CDNs compress JavaScript before sending it, and repetitive text like whitespace and long names compresses well. On our cart sample the raw file drops 52.6% with Compress + mangle (823 to 390 bytes), but the gzipped size goes from 393 to 277 bytes, a 29.5% cut. The minified, gzipped file is about a third of the original raw size.

The lighter presets show it even more clearly. Strip only saves 20.9% raw but only 17.3% after gzip (393 to 325 bytes). So minify and compress together, and judge your savings on the gzip column, since that's what users actually download. For the rest of a page's weight, the CSS Minifier and Minify HTML tools run the same way.

Frequently Asked Questions

What does minifying JavaScript remove?

A minifier like Terser removes comments and whitespace, shortens local variable names, folds constants, drops unreachable code, and applies safe syntax transforms. The output is functionally identical JavaScript that parses to the same behavior. Unsafe assumptions, like relying on Function.prototype.toString, can break, so test after minifying.

How much smaller is minified JavaScript?

Hand-written JS typically shrinks 30–50% raw, and applying gzip on top commonly cuts 70–80% from the original size. Variable-name mangling contributes most of the raw savings in large files. For production sites this directly improves time-to-interactive on slower connections.

Is Terser still the right choice for ES6+ code?

Yes — Terser was forked specifically to handle modern ECMAScript syntax that the older UglifyJS could not parse. It fully supports ES6 through current syntax like optional chaining and nullish coalescing. Running it in your browser means no Node install is needed for quick one-file minification.

Why did minifying my JavaScript remove my functions?

The Compress + mangle preset treats the file as self-contained, so top-level functions that nothing inside the file calls are removed as dead code, and top-level names are shortened. Functions called from HTML onclick attributes or other scripts disappear. Use the Compress preset, or assign the function to window so it stays public.

Does minifying JavaScript keep license comments?

Only with the Compress + mangle preset, which keeps comments starting with /*! or containing @license or @preserve. The Strip only and Compress presets remove every comment, so paste any required license header back in afterwards.