Skip to content
Back to field notes
ExposureJune 6, 20266 min read

How to disable source maps in Vite production builds

A Vite production build does not emit source maps by default, yet many deployed apps still serve .js.map files. This note shows how to keep them off in vite.config and verify it on the public URL before you launch.

ViteSource mapsBuild output

Start at the Vite config, not the theory

This is a fix note for Vite, not a primer on what source maps are or why a public one is a problem. For that background, read Source maps and public exposure in vibe-coded apps. Here the goal is narrow: make sure your deployed Vite app does not serve .map files, and confirm it from the outside.

The setting that controls this lives in your Vite config, in vite.config.ts or vite.config.js, under the build key. It is build.sourcemap. The honest starting point is that Vite's build.sourcemap defaults to false, so a stock vite build does not write .map files into your dist output. If you never touched the setting and you are not running a framework on top of Vite, you may already be fine. The value of checking is that several common situations turn maps back on without you deciding to.

  • The setting is build.sourcemap in vite.config.ts or vite.config.js.
  • Its documented default is false, so plain Vite production builds emit no source maps.
  • A public .js.map is an exposure of build output, not a code bug. The app works exactly the same whether the map ships or not, which is why this stays invisible until someone requests the file.

Why .map files end up public anyway

If the default is off, the interesting question is how a deployed app ends up serving maps regardless. There are a few routes, and AI-generated projects hit more than one of them.

A starter template or boilerplate may set build.sourcemap to true on purpose, so the maintainer could debug. You inherit that line when you scaffold from it. An AI-generated vite.config can add sourcemap: true while wiring up an error monitor, or simply because the model pattern-matched a config that included it. A framework layered on top of Vite sets its own default: Vite is the build tool under several frameworks, and the framework, not raw Vite, decides whether production maps are emitted, so the build.sourcemap default does not necessarily apply to your project. And a deploy that copies the whole dist directory to the host will publish any .map file sitting next to the .js file, because the map is just another static asset in that folder.

  • A template or boilerplate shipped build.sourcemap: true, and you scaffolded from it.
  • An AI-generated config added sourcemap: true, often alongside monitoring setup.
  • A framework on top of Vite (its own config or preset) enabled production maps regardless of Vite's default.
  • The build wrote .map files and the deploy served the whole output directory, so the maps went public with the bundle.

Dev and build are different. Vite's dev server always serves source maps so the browser debugger works, and that is fine, because the dev server runs on your machine, not on the public URL. This note is only about the production build output that gets deployed. Do not try to disable maps in dev; you only care about what ships.

Check your own deployed assets

You can confirm the state of your live app without any attack, because you are only requesting your own files. Do this against your own production URL.

First, look at the built bundle. Open your deployed app in a clean browser session, open DevTools, and load a page so the JavaScript fetches. In the Sources panel, original file names and folder structure showing up (rather than minified one-letter variables) means a map is being applied. You can also open one of your production .js files directly and read the last line: a comment that begins with sourceMappingURL pointing at a .js.map file tells you a map is referenced.

Then test the map URL itself. Take the .js asset path from the Network tab, append .map, and request it. For example, if your bundle is at /assets/index-a1b2c3.js, request /assets/index-a1b2c3.js.map and watch the status code.

  • Suspicious result: the .js.map URL returns a 200 with a JSON body containing your source paths and original code. That is a public source map.
  • Safer result: the .js.map URL returns a 404 or 403, and your production .js files carry no sourceMappingURL comment. That is what an off build looks like from outside.
  • Watch for soft 200s: a single-page app may answer every unknown path with the index HTML and a 200. That is not a map. The leak is a 200 whose body is source-map JSON (it starts with a version field and lists sources), not your HTML page.

Set build.sourcemap to false and keep it there

The fix is one explicit line plus a habit of keeping it explicit. Even though false is the default, setting it deliberately stops a future template merge or AI edit from quietly flipping it.

In vite.config.ts (or .js), inside the config you export, set build.sourcemap to false. Concretely, the build object gets a sourcemap key with the value false: build: { sourcemap: false }. After changing it, delete your old dist output, run a fresh production build, and confirm no .map files were written into the output directory. Then redeploy, because the change only takes effect once the new build is the one being served.

If you are on a framework that uses Vite under the hood, the build.sourcemap line in a raw vite.config may not be the lever the framework reads. In that case set the production-source-map option the framework documents instead, and treat raw Vite config as a hint, not the control. The sibling notes for Next.js and Nuxt cover those framework-specific switches.

  • Add build.sourcemap: false explicitly in vite.config so the off state is intentional, not just inherited.
  • Rebuild from a clean dist and confirm the output directory contains no .js.map files.
  • Redeploy, then re-check the live URL, because a config change that has not been built and shipped changes nothing about what visitors receive.
  • If you keep maps for error monitoring, upload them privately to that tool from your build pipeline rather than serving them from the public bundle.

Turning off maps reduces what a reader can recover from your bundle. It does not make the bundle safe to expose secrets in. Minified JavaScript without a map is still client code anyone can read; an API key or token compiled into the bundle is still extractable. Removing the source map is build hygiene, not a substitute for keeping secrets out of client code in the first place.

Where VibeCodeGuard fits, and what it does not prove

VibeCodeGuard's Launch Check looks at your public surface and checks whether source-map URLs return content. After you set build.sourcemap to false, rebuild, and redeploy, re-run the scan against the live URL. It is the external verification step that the config change actually reached production: the scan requests the map paths an anonymous visitor would and flags any that answer with map content, so you find out from the outside whether maps are still being served.

What it confirms is reachability on the URL you are about to share, not the contents of your repository. It does not read your vite.config, it cannot tell you a map was already scraped while it was public, and it does not review the bundle for secrets that should never have been there. So a clean result means these map paths did not answer on this scan, not that the build is otherwise correct.

Next step: append .map to one of your deployed .js asset paths and request it against your own production URL. If it returns a 200 with source-map JSON, set build.sourcemap to false in vite.config, rebuild from a clean dist, redeploy, and run a focused Launch Check before you share the URL publicly.

A clean Launch Check on source maps is one quiet signal, not a guarantee about the rest of the bundle. The scan sees what is reachable from the public URL; it does not prove your client code is free of secrets or that a map was never exposed before this build. Treat a flagged .js.map as a launch item, fix it in the config, and rebuild before sharing the link.

> launch check

Scan the public surface before launch.

Get severity, evidence, and practical fix guidance for the checks VibeCodeGuard can run from the outside.