What options does Terser provide for mangling and compression?

Updated

Terser exposes two main option groups that control how it shrinks JavaScript: mangle options (rename variables, functions, and properties) and compress options (remove dead code, fold constants, simplify expressions). You pass them as a plain object to the Node.js API or as flags to the CLI. The defaults are already aggressive enough for most production builds, so the practical work is usually knowing which options to turn off when something breaks.

Terser describes itself as an "industry-standard minifier for JavaScript code" that "shrinks variable names, removes whitespace and comments, and drops unused code," usable "through the Command line or Node.JS API." Everything below maps to that mangle/compress split.

Mangle options

Mangling is the step that shortens identifiers. It runs after compression and is the main reason minified output is unreadable.

Option Type What it does
mangle boolean or object Master switch. false disables all renaming; an object configures the sub-options below.
toplevel boolean Also mangle top-level names. Off by default because it can break code that relies on globals.
eval boolean Mangle names referenced inside eval or with. Off by default.
keep_classnames boolean Preserve class names instead of renaming them.
keep_fnames boolean Preserve function names. Useful when code inspects fn.name or uses it in stack traces.
reserved string[] A list of names Terser must never rename.
properties object Enable property mangling. This is opt-in and the riskiest mangle feature — see the warning below.

Property mangling is the one to be careful with

By default Terser does not rename object properties, because property names are part of the public shape of your objects and are frequently accessed as strings. Turning on mangle.properties renames them, which breaks any code that reads a property by a computed or external string — for example obj["userName"], JSON payloads, or DOM/API contracts. If you enable it, use properties.reserved or properties.regex to protect the names that must stay stable.

Compress options

Compression is where most of the size reduction comes from. It is a large set of boolean passes, each toggling one optimization. The most consequential ones:

  • drop_console — removes console.* calls. Handy for production, but it also strips logging you may want in staging.
  • drop_debugger — removes debugger statements.
  • dead_code — removes unreachable code.
  • unused — drops unused variables and functions.
  • evaluate — evaluates constant expressions at build time.
  • conditionals — optimizes if/ternary branches.
  • sequences — joins consecutive statements with the comma operator.
  • booleans — simplifies boolean contexts.
  • passes — a number, not a boolean: how many times to run the compress passes. More passes can shrink further at the cost of build time.
  • pure_funcs — an array of function names you declare side-effect-free, so calls to them can be dropped when their result is unused.
  • pure_getters — tells Terser that property access has no side effects, enabling more removal.

You can also disable a pass by setting it to false, which is the usual fix when an optimization changes behavior you depend on.

How to pass options

Node.js API

const { minify } = require("terser");

const code = `function add(a, b) { return a + b; } console.log(add(1, 2));`;

const result = await minify(code, {
  compress: {
    drop_console: true,
    passes: 2
  },
  mangle: {
    toplevel: true,
    keep_fnames: false
  }
});

console.log(result.code);

The first argument is the source (a string or an object mapping filenames to sources), the second is the options object. The resolved output is on result.code.

CLI

The CLI accepts the same options as flags. A typical invocation:

terser input.js -c drop_console=true,passes=2 -m toplevel=true -o output.js
  • -c (or --compress) takes the compress options.
  • -m (or --mangle) takes the mangle options.
  • -o writes to a file instead of stdout.

For anything beyond a couple of flags, a config file is easier to maintain than a long command line, and it keeps the same option names you would use in the API.

Practical guidance

  • Start with defaults. Terser's defaults already mangle and compress; only add options when you have a specific goal (smaller output, no console logs, preserved names).
  • Reach for keep_fnames / keep_classnames first when something breaks. Name-dependent code (reflection, stack traces, some frameworks) is the most common failure mode.
  • Treat mangle.properties as a separate project. It needs a reserved list and thorough testing before it goes anywhere near production.
  • Increase passes only if you measure a gain. It multiplies build time, and the returns diminish quickly.
  • Verify by running the minified bundle, not just by reading it. Compression can change behavior in edge cases, so your test suite is the real check.

The full option list lives in the Terser API and CLI documentation, and the project's REPL lets you paste code and toggle options to see the effect immediately — the fastest way to confirm what a given option actually does to your output.