Source Maps and Minified Code: Debugging Production JavaScript

May 28, 20267 min read

When you minify JavaScript for production, variable names shorten, whitespace disappears, and the entire file may collapse onto a single line. If an error occurs in that minified bundle, the stack trace points to meaningless positions like app.min.js:1:4829. Source maps solve this problem by providing a mapping back to your original source code.

What Source Maps Do

A source map is a .map file that records the relationship between each position in the minified output and the corresponding position in the original source files. When the browser encounters a source map (either referenced in the minified file or loaded separately), DevTools reconstructs the original file names, line numbers, and variable names for debugging.

{
  "version": 3,
  "file": "app.min.js",
  "sources": ["app.js", "utils.js", "api.js"],
  "sourcesContent": ["// original source..."],
  "names": ["fetchData", "response", "data"],
  "mappings": "AAAA,SAASA..."
}

The mappings field uses Base64 VLQ encoding to represent position translations compactly. You rarely interact with it directly — your bundler generates it, and the browser consumes it.

Generating Source Maps

Every major bundler supports source map generation. The configuration varies slightly:

Vite (Rollup under the hood):

// vite.config.js
export default defineConfig({
  build: {
    sourcemap: true,              // standard source maps
    // sourcemap: 'hidden',       // generate .map files but omit the comment
  }
})

Webpack:

// webpack.config.js
module.exports = {
  devtool: 'source-map',        // full source maps
  // devtool: 'hidden-source-map', // no referencing comment
  // devtool: 'nosources-source-map', // mappings only, no source content
}

esbuild:

esbuild app.js --bundle --sourcemap --outfile=dist/app.min.js

The hidden variant generates the .map file but omits the //# sourceMappingURL=... comment from the minified output. This is important for production security — more on that below.

Source Map Types Compared

Devtool ValueBuild SpeedReconstruction QualitySource Content IncludedProduction Safe
source-mapSlowFullYesWith hidden variant
hidden-source-mapSlowFullYesYes
nosources-source-mapSlowLine/column onlyNoYes
cheap-module-source-mapMediumLine-levelYes ❌ partiallyNo
eval-source-mapFastFullYes (in eval)No

For production, hidden-source-map is the recommended choice. It gives you full debugging capability through error monitoring tools without exposing source maps to the public.

Debugging With Source Maps

When source maps are available, browser DevTools shows original file names and line numbers automatically:

  1. Open DevTools → Sources panel
  2. DevTools detects the sourceMappingURL comment and fetches the .map file
  3. The Sources panel displays the original files from the sources array
  4. Breakpoints, console.log locations, and stack traces reference the original code

Without source maps, you see app.min.js:1:4829. With them, you see api.js:45:12 — exactly where the error occurred in your source.

Important: Source maps only affect DevTools display. The browser still executes the minified code. Source maps do not change runtime behavior.

Source Maps in Error Monitoring

Source maps are critical for production error tracking. Services like Sentry, Bugsnag, and Datadog consume uploaded source maps to show readable stack traces for unhandled exceptions.

The typical workflow:

  1. Build your project with hidden-source-map
  2. Upload .map files to your error monitoring service via CLI or API
  3. Deploy minified files to production (without .map references)
  4. When an error occurs, the monitoring service matches the stack trace against uploaded source maps
# Sentry CLI example
sentry-cli releases files <version> upload-sourcemaps ./dist \
  --url-prefix "~/assets/js" \
  --strip-common-prefix

Keep source maps versioned with your releases. If the deployed bundle does not match the uploaded source map version, reconstructed stack traces will be incorrect.

Security Considerations

Exposing source maps publicly means anyone can view your original source code — including proprietary logic, API endpoints, and internal comments.

Risks of publicly accessible source maps:

  • Source code exposure — competitors or attackers can inspect your business logic
  • API key discovery — comments may contain credentials mistakenly committed
  • Attack surface mapping — attackers identify vulnerable code paths more easily

Mitigation strategies:

  • Use hidden-source-map — no sourceMappingURL comment in the minified file
  • Serve .map files on an internal domain — restrict access via authentication or IP allowlists
  • Delete .map files from production servers — after uploading to your error monitoring service
  • Use nosources-source-map — includes position mappings but omits original source content

The nosources variant is a middle ground: error monitoring tools still get correct line numbers, but nobody can read your actual code through the source map.

Key Takeaways

  • Source maps map minified code positions back to original source files for debugging
  • Generate them with hidden-source-map for production — full fidelity without public exposure
  • Upload source maps to error monitoring services (Sentry, Bugsnag) for readable production stack traces
  • Never deploy .map files to public servers — they expose your original source code
  • Source maps only affect DevTools display; they do not change runtime behavior

Try It Yourself

See minification in action with our free JavaScript Minifier. Paste your code, compare the original and minified output, and understand why source maps are essential for production debugging.