Modern JavaScript bundlers like ESBuild, Webpack, and Rollup transform modular, multi-file codebases into highly optimized single-file bundles. In production deployments, code is minified: whitespace is stripped, identifiers are renamed to single characters, statements are collapsed using comma operators, and module imports are converted into internal helper functions.
When source maps are missing, understanding or auditing this code requires systematic unminification. In this guide, we break down how ESBuild bundle structures work and how to restore readable code from obfuscated artifacts.
1. Anatomy of an ESBuild Bundle
ESBuild handles ES Modules (ESM) and CommonJS (CJS) by synthesizing lightweight wrapper functions. The most common patterns you will encounter in minified bundles are:
__esm(fn): Lazy-evaluates an ES module once and caches the namespace.__toESM(mod): Wraps CommonJS exports to expose standard default and named properties.__export(target, all): Defines getters on module exports to simulate live ESM bindings.
// Typical minified ESBuild module wrapper:
var s=Object.defineProperty;
var i=Object.getOwnPropertyDescriptor;
var p=(t,e)=>{for(var r in e)s(t,r,{get:e[r],enumerable:!0})};
var m=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Object.getOwnPropertyNames(e))!Object.prototype.hasOwnProperty.call(t,n)&&n!==r&&s(t,n,{get:()=>e[n],enumerable:!(a=i(e,n))||a.enumerable});return t};
var d=t=>m(s({},"__esModule",{value:!0}),t);
2. The Comma Operator Compression Pattern
Minifiers frequently replace sequential statements with chained expressions using the comma operator (a(), b(), c()) or ternaries (cond ? (x=1, y=2) : z=3). This saves bytes by eliminating semicolons and statement blocks, but destroys human readability.
To decompile these structures:
- Expand chained comma expressions into distinct statement lines.
- Convert ternary assignments back into explicit
if / elsecontrol flow blocks. - Reformat nested ternary chains into readable
switchorif / else ifbranches.
3. Variable Recovery and Identifier Mapping
While variable renaming (mangling) is irreversible without source maps or symbols, identifiers can be contextualized based on their usage patterns:
- DOM elements:
document.getElementByIdorquerySelectortargets indicate UI references. - Web APIs: Calls to
fetch(),crypto.subtle, orlocalStoragereveal network and storage handlers. - Data models: Object property names (which are preserved unless advanced property mangling is used) provide structural hints.
Try the In-Browser Decompiler
Paste your minified ESBuild or Webpack JavaScript payload into our client-side decompiler to instantly unpack IIFEs, expand comma-statements, and format readable code.