Source Maps and Minified Code: Debugging Production JavaScript
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 Value | Build Speed | Reconstruction Quality | Source Content Included | Production Safe |
|---|---|---|---|---|
source-map | Slow | Full | Yes | With hidden variant |
hidden-source-map | Slow | Full | Yes | Yes |
nosources-source-map | Slow | Line/column only | No | Yes |
cheap-module-source-map | Medium | Line-level | Yes ❌ partially | No |
eval-source-map | Fast | Full | Yes (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:
- Open DevTools → Sources panel
- DevTools detects the
sourceMappingURLcomment and fetches the.mapfile - The Sources panel displays the original files from the
sourcesarray - Breakpoints,
console.loglocations, 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:
- Build your project with
hidden-source-map - Upload
.mapfiles to your error monitoring service via CLI or API - Deploy minified files to production (without
.mapreferences) - 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— nosourceMappingURLcomment in the minified file - Serve
.mapfiles on an internal domain — restrict access via authentication or IP allowlists - Delete
.mapfiles 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-mapfor production — full fidelity without public exposure - Upload source maps to error monitoring services (Sentry, Bugsnag) for readable production stack traces
- Never deploy
.mapfiles to public servers — they expose your original source code - Source maps only affect DevTools display; they do not change runtime behavior
Related Guides
- JavaScript Minification Guide: How It Works and Why It Matters
- Tree Shaking vs Minification
- JavaScript Performance Optimization
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.