mini-css-extract-plugin: SourceMaps for imported SASS partials don't work

assuming we have the following project:

src/components/app/
├── app.js
├── app.scss
├── app.test.js
└── app.vue

the app.vue file:

<template>
  <div id="app" class="app" v-if="isReady">
   <!--some html here-->
  </div>
</template>

<script src="./app.js"></script>
<style src="./app.scss" lang="scss"></style>

And the app.scss file is just a series of imports to partials:

@import 'reset';
@import 'variables';
@import 'base';
@import 'form';
@import 'buttons';
@import 'icons';
@import 'slider';
@import 'helpers';
@import 'misc';

mini-css-extract correctly creates an app.css file. I use devtool: 'source-map', to enable sourceMaps.

When inspecting the HTML/CSS, I don’t see the actual partial file, but only app.scss as the source of my code.

Configuration:

      // build/webpack.base.conf.js
      {
        test: /\.scss$/,
        use: [
          MiniCSSExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            }
          },
          { loader: 'postcss-loader', options: { sourceMap: true } },
          {
            loader: 'sass-loader',
            options: {
              includePaths: [config.build.sassVariables],
              data: '@import "variables";@import "mixins/mixins";',
              sourceMap: true,
            }
          },
        ]
      }

The above worked fine with extract-text-webpack-plugin

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 17
  • Comments: 38 (10 by maintainers)

Most upvoted comments

I eventually found my issue in the original codebase I had the problem in… Similar to above, we were using postcss-loader and weren’t setting sourceMap: true.

Moral of the story, set sourceMap in every loader … which feels a little smelly given that Webpack has a root devtool config option … I would have thought every loader would respect that option 🤔

@cloakedninjas invalid configuration, please use

module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: true
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true
                        }
                    }
                ]
            }
        ]
    },

Just to second i’ve also got this issue, researching the problem now. Will update if I find anything.

Huh, importing bootstrap at the top of styles.scss causes the source map issues. I’ve almost exorcised bootstrap from our codebase, so this might not be an issue for me for much longer, but it’s still interesting.

any idea how to not use MiniCssExtractPlugin in dev so that HMR works? this is my config for vue.js so far that extracts css and provides working sourcemaps in firefox and chrome

have tried to remove MiniCssExtractPlugin but to no avail.

var MiniCssExtractPlugin = require('mini-css-extract-plugin')
var path = require('path')

module.exports = {
  configureWebpack: {
		devtool: 'source-map',
		resolve: {
		  alias: {
				'include-media': path.join(process.cwd(), '/node_modules/include-media/dist/_include-media.scss'),
				'bourbon': path.join(process.cwd(), '/node_modules/bourbon/core/_bourbon.scss'),
		  }
		},
		module: {
		  rules: [
		  	process.env.NODE_ENV === 'development' ?
				({
				  test: /\.scss$/,
				  use: [
					  MiniCssExtractPlugin.loader,
					  {
						  loader: 'css-loader',
						  options: {
							  sourceMap: true
						  }
					  },
					  {
						  loader: 'sass-loader',
						  options: {
							  sourceMap: true
						  }
					  },
				  ]
			  }) : {},
			  {
			    test: /\.css$/,
			    use: [
			  		process.env.NODE_ENV !== 'production' ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
			  		{ loader: 'css-loader' }
			    ]
			  }
		  ]
		},
		plugins: [
		  new MiniCssExtractPlugin({
				filename: 'custom.css'
		  }),
		]
  }
}

project structure

    ├── package.json
    ├── public
    │   ├── application.css
    │   ├── favicon.ico
    │   ├── index.html
    │   ├── normalize.css
    │   ├── svg
    │   │   ├── check.svg
    │   │   └── menu.svg
    │   └── theme.css
    ├── vue.config.js
    └── src
        ├── assets
        │   └── logo.png
        ├── components
        │   ├── BottomFooter
        │   │   ├── BottomFooter.vue
        │   │   └── style.scss
        │   ├── Navigation
        │   │   ├── Navigation.vue
        │   │   └── style.scss
        │   └── Test
        │       ├── Test.vue
        │       └── style.scss
        ├── containers
        │   └── App
        │       ├── App.vue
        │       └── styles
        │           ├── _base.scss
        │           ├── _custom.scss
        │           ├── _fonts.scss
        │           ├── _vars.scss
        │           ├── shared
        │           │   ├── _animations.scss
        │           │   ├── _buttons.scss
        │           │   ├── _forms.scss
        │           │   ├── _functions.scss
        │           │   ├── _gradients.scss
        │           │   ├── _icons.scss
        │           │   ├── _inputs.scss
        │           │   ├── _links.scss
        │           │   ├── _mixins.scss
        │           │   ├── _modals.scss
        │           │   ├── _selects.scss
        │           │   ├── _shared.scss
        │           │   └── _type.scss
        │           ├── style.scss
        │           └── vendor
        │               └── _vendor.scss
        ├── main.js
        ├── router.js
        ├── svg
        │   ├── check.js
        │   ├── index.js
        │   └── menu.js
        └── views
            ├── Home
            │   ├── Home.vue
            │   └── style.scss
            └── Test
                ├── Test.vue
                └── style.scss

vue component setup

<style lang='scss' src='./style.scss' />

<script>

	export default {
		name: 'test',
	}

</script>

<template>
	<div class='Test'>
		Test
	</div>
</template>

scss setup

@import '~@/containers/App/styles/vars';
@import '~@/containers/App/styles/shared/type';
@import '~include-media';

/* test
************************************************/
	.test {
		border: 10px solid green;
	}

firefox 65.0.1 image

chrome Version 72.0.3626.121 image

when cmd+clicking into the property it locates it on the correct line in the correct partial: image

however, there is no HMR!

Any update on this? Having the same issue, the sourcemap points to a single concatenated .SCSS file but we don’t @import .css files

I eventually found my issue in the original codebase I had the problem in… Similar to above, we were using postcss-loader and weren’t setting sourceMap: true.

Moral of the story, set sourceMap in every loader … which feels a little smelly given that Webpack has a root devtool config option … I would have thought every loader would respect that option 🤔

This worked for me 😃

             {
                        loader: "postcss-loader",
                        options: {
                            plugins: [
                                require('autoprefixer')({
                                    browsers: ['last 2 versions', 'ie > 8']
                                })
                            ],
                            sourceMap: true //⚠️ ⚠️Be sure sourceMap is enabled ⚠️
                        }
                    },

There is a problem with node-sass at the moment, and it breaks when handling sourcemaps and variables (mine broke when handling maps)

Get yourself:

  • webpack-shell-plugin,
  • a batch file called compile-sass.bat at root with a couple lines of
start /b node-sass --output-style compressed ./path/to/entry.scss ./path/to/output.css --source-map-embed
  • mini-css-extract-plugin, with these configs in your plugins
new MiniCssExtractPlugin( {
            filename: '..path/to/[name].css',
            chunkFilename: 'path/to/[id].css',
            sourceMap: true
        } ),
        new webpackShellPlugin( {
            onBuildStart: [ `compile-sass.bat` ]
        } ),

after that, include the individual files(one file per line in your batfile) if in development, and if in production, just include the single main.css that doesn’t have any sourcemaps, cause those don’t belong in production.

Hope this helps someone.

It’s strange because the file and line number reported by Chrome are correct but when I click on the file link in Chrome it goes to this massive concatenated SCSS file. Anything in an imported file is linking fine though.

I was planning on it. I really wanted to make sure it was postcss-loader though. I’ll get you something in a bit.

Using devtool: 'inline-cheap-source-map' provisionally works for me

@evilebottnawi here’s the minimum viable reproducible: node-sass --output compact input.scss output.css --source-map on any scss/sass file with a map.

It’s not your plugin, it’s node-sass itself.

In my case I am using gulp-sass and have source maps from gulp.sourcemaps and also provided as option to gulp-sass but the similar bug I can see. However, as soon as I removed bootstrap from gulp-sass includedPaths the sourcemaps are fine. Seems a problem with node-sass ?

Ok, I can try doing it today