JavaScript Beautifier & Minifier
Pretty-print or minify JavaScript with real AST. Beautify via js-beautify, minify via Terser. ES2024 syntax supported.
JavaScript Beautifier / Minifier
Runs entirely in your browser. Your input never leaves your device.
What next?
How it works
Two different problems: formatting and minification
JavaScript formatting and minification sound like opposites of the same operation, but they involve fundamentally different techniques.
Formatting (beautify) is cosmetic: add indentation, normalize spacing, insert newlines at logical boundaries. The output is semantically identical JavaScript — same tokens, same behavior.
Minification is semantic compression: remove all whitespace, rename local identifiers to shorter names, eliminate dead code paths, collapse constant expressions. The output is functionally equivalent JavaScript but the tokens change. You cannot reliably reverse minification back to readable source (hence the need for source maps).
This tool uses js-beautify for formatting and Terser for minification. These are best-in-class for each role.
AST-based vs regex-based formatters
A regex-based formatter processes JavaScript as text: it looks for patterns like { followed by a newline and inserts indentation. This works for simple cases but fails on edge cases:
- Template literals containing
{— a naive regex may insert indentation inside a template string, corrupting its content. - Destructuring patterns — nested
{inconst { a: { b } } = objgets misread. - Regular expression literals —
/[{(]/glooks like an opening block to a text-based parser.
An AST-based formatter first parses the JavaScript into an Abstract Syntax Tree — a structured representation where every node knows its type (FunctionDeclaration, ArrowFunctionExpression, TemplateLiteral, etc.). Formatting decisions are then made on the tree, not on text. Template literals are never incorrectly indented because the parser knows their boundaries.
js-beautify uses an AST-aware approach and handles ES2024 syntax including optional chaining, nullish coalescing, logical assignment operators, top-level await, and class fields.
Terser: real AST minification
Terser is the standard JavaScript minifier for production web builds. It is what Vite, webpack (via terser-webpack-plugin), and esbuild use internally or offer as an alternative. Its key capabilities:
Whitespace removal — all insignificant whitespace, comments, and newlines are stripped.
Name mangling — local variable names are renamed to single or double characters: function calculateTaxableIncome(amount, rate) becomes function a(b,c). This is the largest contributor to size reduction beyond whitespace. Exported names are preserved by default (Terser understands ES module export boundaries) because renaming exports would break callers. Mangle only applies to names that are local to the scope.
Dead code elimination — unreachable branches are removed:
// Before
if (false) {
console.log('never runs');
}
const DEBUG = false;
if (DEBUG) { heavyOperation(); }
// After (Terser with evaluate: true)
// Both blocks removed entirely
Constant folding — expressions that evaluate to a constant at parse time are collapsed:
const MS_PER_DAY = 24 * 60 * 60 * 1000;
// Becomes:
const MS_PER_DAY = 86400000;
Mangle toggle: when to enable and when not to
The mangle option renames local identifiers. You want it on for production browser bundles — it is the single biggest size reduction after whitespace removal.
Disable mangle when:
- You're minifying Node.js code that uses
Function.prototype.nameto identify functions by name at runtime. - You're minifying code that gets
eval()'d or usesnew Function()with string arguments referencing local variable names. - You need the minified output to still be debuggable without source maps (rare, but valid in some embedded contexts).
- The code uses
withstatements (extremely rare in modern JS; Terser will warn).
Before/after byte count
The tool shows input byte count, output byte count, and percentage saved. A few realistic examples:
| Code type | Typical saving (whitespace only) | With mangle | |-----------|----------------------------------|------------| | Utility library (lodash-style) | 20–30% | 50–65% | | React component file | 25–35% | 45–60% | | Configuration-heavy file | 15–20% | 20–30% | | Already compact code | 5–15% | 15–25% |
The percentage matters most for code that ships directly to browsers without bundler processing. For already-bundled apps, your bundler handles minification — use this tool for one-off scripts, CDN-hosted libraries, and inline scripts.
Tree shaking: what Terser cannot do
A common misconception: Terser can eliminate dead code within a file but it cannot do cross-file tree shaking. Tree shaking — removing exported functions that no module ever imports — requires bundler-level analysis (Rollup, Vite, webpack). Terser sees one file at a time and doesn't know which exports are consumed.
If you paste a utility library into this tool hoping to remove functions you don't use, Terser will not remove them — it will only minimize the code that's there. For library-level tree shaking, use a bundler with a proper entry point.
Source maps for production debugging
Minified code in production is unreadable in stack traces. Source maps solve this by mapping minified byte positions back to original source lines. Terser generates inline or external source maps:
import Terser from 'terser';
const result = await Terser.minify(code, {
mangle: true,
compress: true,
sourceMap: {
filename: 'app.min.js',
url: 'app.min.js.map',
},
});
// result.code — minified JavaScript with sourceMappingURL comment
// result.map — source map JSON
Upload both files. The sourceMappingURL comment at the end of the minified file points DevTools to the map. Error monitoring services (Sentry, Datadog) can consume source maps server-side to show original stack frames in alerts.
ES2024 syntax support
Terser supports modern JavaScript through ES2024:
- Optional chaining (
?.) and nullish coalescing (??) - Logical assignment (
&&=,||=,??=) - Top-level
await - Class fields (public, private
#field, static) Object.hasOwn()andArray.at()using/await using(Explicit Resource Management, Stage 4)
Set ecma: 2024 in Terser's compress options to enable optimizations specific to modern syntax.
Faster alternatives: SWC and esbuild
For build pipelines where speed matters more than maximum compression:
- esbuild (Go) — 10–100× faster than Terser, good enough minification for most apps. Limited dead code elimination compared to Terser.
- SWC (Rust) — used by Next.js and Parcel. Very fast, improving minification quality rapidly.
For a browser-based one-off tool, speed is not the bottleneck — Terser's more aggressive optimization is preferable.
Privacy
All JavaScript processing runs in your browser. Your code is never transmitted to a server.
FAQ
What is the difference between beautify and minify?
Beautify is cosmetic: it adds indentation, normalizes spacing, and inserts newlines to make code readable. The JavaScript tokens are unchanged and execution behavior is identical. Minify is compression: it removes whitespace, renames local variables to shorter names, and eliminates dead code. The output is functionally equivalent but tokens change and the code is intentionally unreadable. Minification is a one-way transformation — you cannot recover the original variable names without a source map.
Why does this tool use Terser for minification instead of just removing whitespace?
Whitespace removal alone saves 15–25% of file size. Terser's full minification (whitespace + name mangling + constant folding + dead code elimination) saves 45–65% for typical application code. The difference is name mangling: renaming calculateMonthlyInterestRate to a across an entire file produces substantial savings because identifiers appear many times. Terser uses a real AST parser so it safely renames only local identifiers, never exported names or globals.
What does "mangle" mean?
Mangling renames local variables, function parameters, and internal function names to the shortest possible identifiers — typically single characters. function processUserInput(rawValue, options) becomes function a(b,c). Exports and globals are preserved because renaming them would break callers. Enable mangle for production browser bundles; disable it if your code inspects Function.prototype.name at runtime or uses eval() referencing local variable names by string.
Can Terser remove unused functions from a library?
Only within a single file. Terser eliminates dead code it can prove is unreachable — e.g., if (false) { ... } blocks, constants that evaluate to falsy. It does not perform cross-file tree shaking (removing exported functions no one imports). That requires bundler-level analysis from Rollup, Vite, or webpack. For removing unused library exports, use a bundler with a proper entry point rather than this tool.
Does minification work correctly with modern JavaScript syntax?
Yes. Terser supports through ES2024 including optional chaining (?.), nullish coalescing (??), logical assignment (&&=, ||=, ??=), class private fields (#field), top-level await, and the Explicit Resource Management proposal (using). Set ecma: 2024 in Terser options for modern-syntax-specific optimizations.
Why does beautified code sometimes differ from Prettier's output?
js-beautify and Prettier make different style decisions. Prettier is opinionated and produces a single canonical format with no configuration. js-beautify is configurable and may differ on things like object spacing, function argument spacing, or brace style. For a codebase with a Prettier config, run Prettier instead. Use this tool for quick one-off formatting where you don't want to install anything.
How do I debug production errors in minified JavaScript?
Generate a source map during minification and upload it to your error monitoring service (Sentry, Datadog, Bugsnag) or host it alongside the minified file. The source map encodes the mapping from each minified character position back to the original source line and column. Browser DevTools and error monitoring services automatically use source maps to show original stack traces and the original source file when debugging.
Is my JavaScript code sent to a server?
No. Both js-beautify and Terser run entirely in your browser compiled to WebAssembly and JavaScript. No code is transmitted to any server. This applies even to private code, internal utilities, or proprietary application logic — nothing leaves your device.