EthicsComputerCourses
Join training +91 90532 10052

Source Maps & Production Builds

Sass · Lesson 24 of 26 Advanced 7 min read Updated

Once your styles are spread across twenty partials, a new problem appears. You open the browser's developer tools, inspect a button and see main.css line 412. Which of your SCSS files wrote that rule? A source map answers that question. And when the site goes live, you want the opposite: the smallest CSS file possible, with no development extras.

In this lesson you will see what a source map contains, use it in the browser, choose between the source map options, and set up separate development and production builds.

What a source map is

When Dart Sass writes a CSS file, it also writes a .map file next to it, unless you tell it not to. Take a small project with a partial and an entry file:

SCSS
// scss/_button.scss
$brand: #0e7490;

.btn {
  background: $brand;
  color: white;
}

// scss/main.scss
@use "button";

body {
  margin: 0;
}

Compile it with npx sass scss/main.scss css/main.css and you get two files. The CSS ends with a special comment that points to the map:

CSS
.btn {
  background: #0e7490;
  color: white;
}

body {
  margin: 0;
}

/*# sourceMappingURL=main.css.map */

The map itself is a small JSON file:

JSON
{"version":3,"sourceRoot":"","sources":["../scss/_button.scss","../scss/main.scss"],"names":[],"mappings":"AAEA;EACE,YAHM;EAIN;;;ACFF;EACE","file":"main.css"}
  • sources lists every SCSS file that contributed to the CSS, as paths relative to the map.
  • mappings is a compact code that links each position in the CSS to a line and column in one of the sources.

You never edit a map by hand. The browser reads it.

Using the map in the browser

Open the page in Chrome, Edge or Firefox, right-click the button and choose Inspect. In the Styles panel, the rule for .btn is now labelled _button.scss:3 instead of main.css:1. Click the label and the browser opens your SCSS file at the right line. Source maps are on by default in the developer tools of these browsers; if you see main.css instead, check the settings for "Enable CSS source maps".

For this to work, the browser must be able to download the map and the SCSS files it lists. That is easy on your own computer, and it is why the next options exist.

Source map options

FlagEffectWhen to use
(none)Writes main.css.map with relative pathsNormal local development
--no-source-mapNo map at allProduction builds
--embed-sourcesCopies the SCSS text into the mapWhen the SCSS files are not served next to the CSS
--embed-source-mapPuts the whole map inside the CSS comment, no .map fileQuick single-file setups
--source-map-urls=absoluteUses file:/// pathsOnly works on the computer that compiled it

In Vite, CSS source maps in the dev server are off by default; set css: { devSourcemap: true } in vite.config.js to turn them on.

Development vs production

During development you want readable CSS and maps. On the live site you want small files and nothing extra. The compiler itself cannot tell which you need, so make two npm scripts:

JSON
{
  "scripts": {
    "dev": "sass --watch scss:css",
    "build": "sass --style=compressed --no-source-map scss:css"
  }
}

npm run build on the example project gives a single line:

CSS
.btn{background:#0e7490;color:#fff}body{margin:0}

Compressed output removes whitespace and normal comments, and uses the shortest form of values. Only /*! comments survive (see Comments). Your web server should also send CSS gzip or brotli compressed, which shrinks it much further; that is a server setting, not a Sass one.

What the browser receives

You can check what a build will contain right here. The editor shows the expanded style; the comments show what survives into compressed output:

SCSSTry it yourself
/*! Jaipur Crafts v3.1 | (c) Jaipur Crafts */
// Not in the output: a silent comment
$brand: #b45309;

/* Removed in compressed output */
.product-card {
  border: 1px solid $brand;

  &:hover {
    box-shadow: 0 4px 12px rgb(0 0 0 / 0.15);
  }
}
Output
/*! Jaipur Crafts v3.1 | (c) Jaipur Crafts */
/* Removed in compressed output */
.product-card {
  border: 1px solid #b45309;
}
.product-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

Adding PostCSS after Sass

Many production pipelines run one more tool after Sass: PostCSS with plugins such as Autoprefixer, which adds vendor prefixes for the browsers you support. Sass writes CSS, PostCSS transforms that CSS. With the command-line tools it is two steps:

Terminal
npx sass --no-source-map scss/main.scss css/main.css
npx postcss css/main.css --use autoprefixer --replace

Vite runs PostCSS automatically when it finds a postcss.config.js, after compiling your SCSS. The next lesson, Sass vs PostCSS vs Native CSS, compares the tools.

Common mistakes

  • Uploading main.css but not main.css.map. The comment points to a missing file and dev tools show a 404 warning. Upload both, or build without maps.
  • Shipping expanded CSS to production. Use --style=compressed.
  • Editing the compiled CSS in dev tools and expecting it to save. Changes in dev tools are temporary. Edit the SCSS file the map points to.
  • Committing compiled CSS and maps to Git by accident. Many teams add css/ to .gitignore and build on deploy.

Key points

  • Dart Sass writes a .map file by default; it links every CSS position to the SCSS line that produced it.
  • Browser dev tools use the map to show _button.scss:3 instead of a line in the compiled CSS.
  • --no-source-map, --embed-sources and --embed-source-map control how maps are written; Vite needs css.devSourcemap: true in dev.
  • Use expanded output with maps for development and --style=compressed --no-source-map for production.
  • PostCSS tools such as Autoprefixer can run after Sass in the same build.

Exercise

Set up the build for a Lucknow bakery project with scss/main.scss. Write three npm scripts: dev (watch with source maps), build:css (compressed, no maps) and build (runs build:css, then Autoprefixer on css/main.css with PostCSS). Explain in one sentence why the map should not be deployed if the SCSS files are not uploaded to the server.

Show solution
JSON
{
  "scripts": {
    "dev": "sass --watch scss:css",
    "build:css": "sass --style=compressed --no-source-map scss:css",
    "build": "npm run build:css && postcss css/main.css --use autoprefixer --replace"
  }
}

Without the SCSS files on the server (and without --embed-sources), the browser can read the map but cannot fetch the sources it lists, so the map only causes 404 warnings and adds nothing.

Quick Quiz

1. What does a Sass source map do?

2. Which command is right for a production build?

3. What does --embed-source-map change?

4. Which tool commonly runs after Sass to add vendor prefixes?

Learn Sass with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call