ToolSite

JavaScript Minification 101: What Actually Gets Removed?

What JS minification removes: whitespace, comments, dead code, mangled names. Terser before-and-after examples with real size numbers. Try our free minifier.

By ToolSite5 min readguides

What JavaScript Minification Is

JavaScript minification transforms source code into a smaller, functionally identical version by removing everything the runtime does not need. Unlike compression (gzip, brotli), which operates on bytes, minification operates on source tokens. The output is still valid JavaScript that any engine can execute.

A minifier does not change what your code does. It changes how the code is written. Shorter names. Fewer characters. No comments. The logic stays intact.

What Gets Removed

Whitespace and Newlines

The most straightforward optimization. Spaces, tabs, and newlines that separate tokens are stripped:

// Before: 66 characters
function add(a, b) {
  const sum = a + b;
  return sum;
}

// After: 32 characters
function add(a,b){return a+b}

The JavaScript parser uses token boundaries from the grammar, not whitespace. Between function and add, it knows one token ends and another begins. The whitespace is only for human readers.

Across a real file, whitespace accounts for roughly 20 to 30 percent of the total byte count. Stripping it is the first and safest optimization.

Comments

All comments disappear. Single-line (//), multi-line (/* */), and JSDoc blocks are stripped in production builds. A 300-line file with generous comments might shed 4 to 5 KB from comment removal alone.

If you need certain comments in production, for license attribution or conditional compilation markers, most minifiers let you preserve comments that match a pattern. Terser preserves comments starting with /*! by default.

Dead Code Elimination

Dead code is code that can never execute. A minifier detects and removes it:

// Before
if (false) {
  console.log("This never runs");
}
// After: empty (the entire if block is deleted)

const DEBUG = false;
if (DEBUG) {
  expensiveDebugCall();
}
// After: both the constant and the dead branch are removed

Modern bundlers (Webpack, esbuild, Rollup) coupled with Terser perform aggressive dead code elimination. Tree-shaking removes entire unused module exports before the minifier touches the file. The two passes complement each other: the bundler removes unused modules, and the minifier removes unreachable code within the remaining modules.

Identifier Shortening (Mangling)

This is where most of the savings come from. Local variable and function names are shortened to single letters:

// Before: 183 characters
function calculateTotalPrice(cartItems, taxRate) {
  const subtotal = cartItems.reduce((sum, item) => sum + item.price, 0);
  const discount = subtotal > 100 ? subtotal * 0.1 : 0;
  return (subtotal - discount) * (1 + taxRate);
}

// After: 104 characters
function a(b,c){const d=b.reduce((e,f)=>e+f.price,0);return(d-(d>100?d*.1:0))*(1+c)}

The function went from 183 characters to 104. A 43 percent reduction on a small function with only descriptive names to compress.

calculateTotalPrice became a. cartItems became b. subtotal became d. taxRate became c. Every identifier local to the function is renamed to the shortest possible non-colliding name.

Global identifiers and exported symbols stay unchanged by default because other modules reference them. If your entire application is bundled into a single file with no external consumers, you can enable property mangling for additional savings. This is more aggressive and requires testing.

Expression Simplification

Minifiers apply constant folding and boolean simplification:

// Before
const minutesInDay = 60 * 24;
const isAdult = age >= 18 ? true : false;
if (!!someValue) { ... }
if (x === undefined) { ... }

// After
const minutesInDay = 1440;
const isAdult = age >= 18;
if (someValue) { ... }
if (x === void 0) { ... }

60 * 24 is computed at build time and replaced with 1440. The redundant ternary ? true : false is eliminated. Double negation !! is removed. undefined becomes void 0, which is two characters shorter and immune to undefined being reassigned in older environments.

Real File Size Numbers

Here are measurements from a 1,200-line utility library before and after Terser minification:

| Pass | Size | Reduction | |---|---|---| | Original source (comments, whitespace) | 38.2 KB | baseline | | Minified (whitespace + comments removed) | 24.1 KB | 37% | | Minified + mangled | 16.8 KB | 56% | | Minified + mangled + gzipped | 5.1 KB | 87% |

The largest single reduction comes from mangling. Descriptive variable names like configurationOptions and requestHandler compress to a and b. Across thousands of identifiers, the savings dominate.

What Minification Is Not

Minification is not obfuscation and not encryption. Anyone with a beautifier can reformat minified JavaScript back to readable code. The logic is fully visible. Variable names are lost but the structure is intact.

Minification also does not hide API keys, tokens, or secrets. If you put const API_KEY = "sk-abc123" in your source, it will appear in the minified output. Never commit secrets to source code.

Minification does not change the runtime behavior of your program. If your code had a bug before minification, the minified version has the same bug.

The Build Pipeline

For modern JavaScript projects, the pipeline is:

  1. Write ES6+ or TypeScript source.
  2. Transpile to a target JavaScript version (optional, for older browsers).
  3. Bundle modules into one or a few files.
  4. Minify the bundled output.
  5. Serve the minified files with gzip or brotli.

Each step reduces size. Transpilation may add size (polyfills, helpers). Bundling removes duplicates. Minification strips everything non-essential. Compression adds the final layer.

Try it yourself: open the JS/TS Minifier. Paste a small JavaScript function with comments, whitespace, and descriptive variable names. Click Minify. Observe how identifiers shorten and comments vanish. Copy the minified output and paste it into a beautifier to verify the logic is intact and semantically identical.

Related Reading