skip to content

How do you give an error-reporting service readable stack traces for an Angular CLI production build without letting browsers download your source maps?

level: middleimportance: should knowfreq 35%

answer

  1. maps without the reference comment
  2. sourceMap object form, hidden
  3. upload in CI, then remove
  4. sourcesContent embeds original code
  5. vendor maps are opt-in

basics

~10 s

Set the production sourceMap to { "scripts": true, "hidden": true }. The builder writes .map files without the sourceMappingURL comment. CI uploads them to the error-reporting service and deletes them before deploying.

solid answer

~40 s

The application builder's `sourceMap` option has an object form, and `hidden: true` is the key part: the `.map` files are still written next to the bundles, but the bundles carry no `//# sourceMappingURL` comment, so browsers never request them. The CI pipeline runs `ng build`, uploads the `.map` files to the error-reporting service tagged with the release, then deletes them from `dist/<project>/browser` before deploying. `styles` can be `false` if only script traces matter, `vendor: true` adds third-party maps when stack traces must reach into libraries, and `sourcesContent: false` keeps original source text out of the maps if the service only needs mappings. Hidden maps do not protect anything if they are deployed anyway, so the delete step is essential.

code

json · 9 lines
json
"production": {
  "outputHashing": "all",
  "sourceMap": {
    "scripts": true,
    "styles": false,
    "hidden": true,
    "vendor": false
  }
}

go deeper

for a junior

Know that source maps map minified code back to the original files, and that production builds do not emit them by default.

for a middle

Use the sourceMap object form, and explain what hidden, vendor and sourcesContent each change.

for a senior

Design the CI flow: build once, upload hidden maps tagged with the release, delete them before deploy, and verify the public server returns 404 for maps.

for a principal

Set the policy for what source leaves the organisation (sourcesContent, vendor maps, retention in the reporting service) and how releases are identified across services.

## The problem A production Angular build is minified: an error report says `TypeError at main-4F2K9.js:1:48213`, which nobody can act on. **Source maps** translate minified positions back to the original files and lines. Deploying maps publicly lets anyone reconstruct the application's source in their browser's developer tools. Teams want readable traces in their error-reporting service and no maps on the public server. ## The application builder's `sourceMap` option `sourceMap` on `@angular/build:application` defaults to `false`. It accepts `true`/`false` or an object: | Property | Default in object form | Effect | |---|---|---| | `scripts` | `true` | Emit maps for JavaScript bundles | | `styles` | `true` | Emit maps for CSS | | `hidden` | `false` | Write external `.map` files **without** the `//# sourceMappingURL` comment | | `vendor` | `false` | Also resolve third-party packages' own source maps | | `sourcesContent` | `true` | Embed original source text inside each map | With `hidden: false`, each bundle ends with a comment pointing at its map, and browser developer tools fetch it automatically when opened. With `hidden: true`, the builder still produces complete `.map` files but the bundles do not reference them. A browser is never told where they are, while a tool that is handed the map explicitly can still use it. ## The pipeline 1. **Configure production** in `angular.json`: - `"sourceMap": { "scripts": true, "styles": false, "hidden": true }`; - keep `optimization` on, since you are mapping the real production code. 2. **Build** in CI with `ng build`. The maps land next to the bundles in `dist/<project>/browser` (and in `server` for SSR builds). 3. **Upload** the `.map` files with the service's upload tool, tagged with the same release identifier the app reports at runtime, so errors match the right maps. 4. **Delete** the `.map` files from the output before the deploy step copies it to the web server or CDN. 5. **Verify** once: request a known map URL from production and expect a 404, and trigger a test error to confirm the service shows original file names. ## Choosing the details - **`styles: false`** saves build time and output when nobody debugs CSS from error reports. - **`vendor: true`** makes traces through library code readable, at the cost of bigger maps and a slower build. Turn it on when many errors originate inside dependencies. - **`sourcesContent: false`** omits the original source text from the maps. The service can then show file names and line numbers but not the code itself unless it has another way to fetch source. Some teams prefer this to limit what is uploaded. - **SSR**: server bundles are mapped by the same option. When scripts maps are on and the build has a server entry, the dev server also enables Node's source-map support for server stack traces. ## One-off debugging builds Sometimes you need maps locally to chase a production-only bug. `ng build --source-map` turns maps on for that single run without touching `angular.json`. The bundles then reference their maps normally, so never deploy the output of such a build. For a fuller local reproduction, build with the production configuration and serve the output folder with any static server. ## What does not work - **`sourceMap: true` and hoping nobody looks.** The reference comment makes maps discoverable by anyone with developer tools. - **Hidden maps left in the deployed folder.** `hidden` hides the reference, not the file. Anyone who guesses `main-<hash>.js.map` can download it. - **Building maps in a separate, unoptimized build.** Positions only match the exact bundle that was deployed, so the maps must come from the same `ng build` run. - **Disabling `optimization` in production to get readable traces.** It makes the app bigger and slower for every user to solve a tooling problem. ## Why interviewers ask It is a practical production question that separates people who have operated an Angular app from people who have only built one. A strong answer names the `hidden` flag, the upload-then-delete step, and the reason the maps must come from the same build.

  • Why must the uploaded maps come from the exact build that was deployed?
    A source map records positions in one specific minified output. Any rebuild can change minification, hashing and chunk boundaries, so a map from another build points to the wrong lines. Build once in CI, upload that run's maps and deploy that run's bundles.
  • What does `sourcesContent: false` change for the error-reporting service?
    The maps keep the position mappings and file names but no longer embed the original source text. Traces still resolve to files and lines, but the service cannot display the surrounding code unless it can fetch the sources another way. It reduces what leaves your CI.

Hidden source maps are like keeping a building's wiring diagram in the maintenance office rather than taped to the lobby wall: the electrician who is handed it can trace every fault, but visitors have no sign that it exists.

saying these in an interview costs you the question

  • Believes hidden: true stops the builder from writing .map files
  • Deploys hidden maps and assumes nobody can download them
  • Turns off optimization in production to get readable stack traces
  • Generates maps from a second build rather than the deployed one
  • Thinks sourceMap true is safe because maps are only fetched by developer tools