Source Maps & Production Builds
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/_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:
.btn {
background: #0e7490;
color: white;
}
body {
margin: 0;
}
/*# sourceMappingURL=main.css.map */The map itself is a small JSON file:
{"version":3,"sourceRoot":"","sources":["../scss/_button.scss","../scss/main.scss"],"names":[],"mappings":"AAEA;EACE,YAHM;EAIN;;;ACFF;EACE","file":"main.css"}sourceslists every SCSS file that contributed to the CSS, as paths relative to the map.mappingsis 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
| Flag | Effect | When to use |
|---|---|---|
| (none) | Writes main.css.map with relative paths | Normal local development |
--no-source-map | No map at all | Production builds |
--embed-sources | Copies the SCSS text into the map | When the SCSS files are not served next to the CSS |
--embed-source-map | Puts the whole map inside the CSS comment, no .map file | Quick single-file setups |
--source-map-urls=absolute | Uses file:/// paths | Only 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:
{
"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:
.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:
/*! 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);
}
}/*! 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:
npx sass --no-source-map scss/main.scss css/main.css
npx postcss css/main.css --use autoprefixer --replaceVite 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.cssbut notmain.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.gitignoreand build on deploy.
Key points
- Dart Sass writes a
.mapfile by default; it links every CSS position to the SCSS line that produced it. - Browser dev tools use the map to show
_button.scss:3instead of a line in the compiled CSS. --no-source-map,--embed-sourcesand--embed-source-mapcontrol how maps are written; Vite needscss.devSourcemap: truein dev.- Use expanded output with maps for development and
--style=compressed --no-source-mapfor 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
{
"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?
Dev tools use the map to show your original SCSS location.
2. Which command is right for a production build?
Compressed output without maps gives the smallest file.
3. What does --embed-source-map change?
The map is embedded as a data URL in the sourceMappingURL comment.
4. Which tool commonly runs after Sass to add vendor prefixes?
Sass writes CSS, then PostCSS plugins such as Autoprefixer transform it.
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
