Skip to content
StackSiren

How do I disable source maps in a Vite production build?

By StackSiren · Published

Set build.sourcemap to false in vite.config (or 'hidden' if you upload maps to an error tracker and delete them before deploy), then rebuild and redeploy. Vite's default is already false, so a public .map on your site usually means someone turned maps on.

Bolt, Lovable and many Cursor-exported apps ship Vite + React. Public maps don't invent new secrets on their own — any key already in the minified bundle is still there — but they make original file names, comments and business logic easy to read. The full background is in the exposed source maps guide.

What production source maps reveal

A source map is a .map file that links minified JavaScript back to the code you wrote. Most production maps include the full original sources, so anyone who downloads one can open your src/ tree as if they had the repo.

That typically means:

  • File and folder names, component structure and route names
  • Comments, TODOs and feature-flag labels left in source
  • Internal API paths and configuration that minification had shortened
  • Secrets that were already in client code, now easy to search

If a secret is in client code because of a VITE_ prefix or a hard-coded key, turn maps off and rotate that secret. See are VITE_ variables secret? and I leaked my OpenAI API key. Our exposed API key checker searches the live bundle on sites you own.

Step 1: Check your own live site

Only check domains you own.

  1. Open the site → DevTools → Sources (or Debugger). If you can browse a readable src/ tree, maps are public.
  2. Or open a production JS file and look at the last line. If it ends with //# sourceMappingURL=..., open that URL. A JSON body with a mappings field means the map is public.

From a terminal:

SITE=https://yourapp.com

# Find JS assets the homepage loads
curl -s "$SITE/" | grep -oE '/assets/[^"]+\.js' | sort -u | head

# For one asset, look for the sourceMappingURL comment
JS=/assets/index-abc123.js   # replace with a real path from above
curl -s "$SITE$JS" | tail -c 200
echo

# If you see sourceMappingURL=index-abc123.js.map, request it
curl -sI "$SITE$JS.map" | head -5
curl -s "$SITE$JS.map" | head -c 200

A 404 / 403 is fine. A 200 with JSON that includes "mappings" is a public map. Some SPA hosts return index.html with status 200 for unknown paths — check the body starts with {, not <!DOCTYPE.

Step 2: Turn maps off in Vite

Vite documents build.sourcemap as boolean | 'inline' | 'hidden', default false.

Open vite.config.ts (or .js) and set:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  build: {
    sourcemap: false, // do not emit .map files in production
  },
});

Notes from Vite's docs:

Value What it does
false (default) No production maps
true Separate .map files + a sourceMappingURL comment in the JS
'inline' Map embedded in the JS as a data URI — usually worse for size and leakage
'hidden' Separate .map files, no sourceMappingURL comment

Remove any sourcemap: true or sourcemap: 'inline' someone (or an AI builder) added for debugging. Rebuild (npm run build / pnpm build) and confirm dist/assets/ has no .map files before you redeploy.

Bolt and Lovable

These are standard Vite projects under the hood. Ask the builder to set build.sourcemap to false in the Vite config and redeploy. If you export to Netlify, Vercel or another static host, the same config applies — don't generate maps you don't need.

Next.js side note

If a project uses Next.js instead of Vite, production browser maps are off unless productionBrowserSourceMaps is true in next.config. Remove it or set it to false.

Step 3: Keep readable stack traces with hidden maps (Sentry)

Error trackers need maps; visitors don't. Sentry's Vite upload guide shows the safe pattern:

  1. Set build.sourcemap: 'hidden' so maps are generated without a browser-facing comment.
  2. Use @sentry/vite-plugin to upload them during the production build.
  3. Set sourcemaps.filesToDeleteAfterUpload so .map files are removed before deploy.

Sketch (replace org/project; store the auth token in CI, not in the repo):

import { defineConfig } from "vite";
import { sentryVitePlugin } from "@sentry/vite-plugin";

export default defineConfig({
  build: {
    sourcemap: "hidden",
  },
  plugins: [
    // other plugins first…
    sentryVitePlugin({
      org: "your-org",
      project: "your-project",
      authToken: process.env.SENTRY_AUTH_TOKEN,
      sourcemaps: {
        filesToDeleteAfterUpload: ["./dist/**/*.map"],
      },
    }),
  ],
});

'hidden' alone is not enough: the .map files still exist on disk, and anyone who guesses the URL can download them if you deploy the folder. Always delete after upload, or configure the host to refuse *.map.

Vercel has a Protected Source Maps option under Deployment Protection that returns 404 to the public for .map files. That helps for maps served from the deployment, but it does not cover maps inlined into JavaScript. Prefer not generating public maps at all.

Step 4: Redeploy and re-check

  1. Rebuild with the new config.
  2. Confirm the build output has no .map files (or that your upload plugin deleted them).
  3. Deploy.
  4. Re-run the curl checks from Step 1 against production.

If DevTools still shows original sources, hard-refresh or try a private window — CDNs and service workers can cache old assets.

Common ways maps end up public

  1. Someone set sourcemap: true for debugging and left it on for production. Vite's default is false; an explicit true is almost always accidental for a public deploy.
  2. An AI builder or template copied a config that enables maps so stack traces look nice in the browser. Prefer hidden maps + an error tracker instead.
  3. 'hidden' without cleanup. Maps are generated and copied into dist, then the whole folder is deployed. Guesses like /assets/index-….js.map still work.
  4. A second build tool (a framework plugin, Rolldown/Rollup override, or a CI step) emits maps even when Vite's top-level option looks off. Always inspect the build output folder before you ship.

If you find maps and also find a secret in the same bundle, treat the secret as leaked: rotate it, then fix how it got into client code. The exposed API keys guide covers that path end to end.

FAQ

Is Vite's default already safe? Yes for maps: build.sourcemap defaults to false. Public maps mean the option was turned on, or another tool emitted them.

Does turning maps off hide API keys? No. Keys in client bundles stay readable in the minified JS. Move secrets server-side and rotate them; maps only make discovery easier.

Is sourcemap: 'inline' OK? Almost never for production. It embeds the map in every JS file, so you ship more bytes and the original source travels with the bundle.

What about 'hidden' without deleting files? Browsers won't auto-load the map, but the files can still be downloaded if deployed. Pair 'hidden' with upload-then-delete (or block *.map on the host).

How do I check this without guessing paths? StackSiren's free scan looks for sourceMappingURL comments on same-origin scripts for sites you own and requests a sample of those map URLs. It won't catch inlined data-URI maps or orphan .map files with no comment.

Bolt / Lovable won't show me vite.config — what then? Ask the builder in chat to set build.sourcemap to false and redeploy. After export to your own repo, edit the config yourself and verify dist before the next deploy.

Check your app now

Free passive scan, results in under a minute.

Run a free scan

Fix guides for this topic

Platform checklists: Bolt · Lovable

Related posts

Sources