webpack-contrib / sass-loader

Compiles Sass to CSS
MIT License
3.91k stars 431 forks source link

nested styles refer to top-level parent in sourcemap line number #272

Closed woohling closed 7 years ago

woohling commented 8 years ago

I encountered the same issue in https://github.com/sass/node-sass/issues/1206. But according to this post, this issue has been fixed in node-sass, but it still occurred with sass-loader.

This is my sass-loader config: 'style!css?sourceMap!sass?sourceMap=true&outputStyle=expanded&sourceMapContents=true'

Any help?

ggedde commented 8 years ago

Mac OSX (El Capitan?) "sass-loader": "^4.0.2", "webpack": "^2.1.0-beta.25", "webpack-dev-server": "^2.1.0-beta.0" node: 6.7.0

When running the SCSS SourceMaps only point to the Parent selector and not the correct selector.

2016-10-22_0150

But as you can see it is not pointing to the correct selector. It should be pointing to line 13 not line 5.

2016-10-22_0156

However, If I run 'node-sass' in the terminal then it works fine. So it seems to be an issue with sass-loader and webpack.

Any solutions to resolve this or is there any settings in node-modules/sass-loader that I can change to get different results.

Thanks

folmert commented 7 years ago

Same problem here. Did anyone found a workaround for this?

jhnns commented 7 years ago

CSS source maps can only work if every loader in the loader chain passes them through. That's necessary because webpack, only supports JS source maps out of the box.

@woohling Do you experience the same issue when you use this loader chain: style-loader?sourceMap!css-loader?sourceMap!sass?sourceMap&outputStyle=expanded&sourceMapContents=true' ?

woohling commented 7 years ago

Just tried, but still the same problem. 😥 @jhnns

folmert commented 7 years ago

I switched from sass-loader to postcss/precss and source maps are generated correctly now, so there must be something broken in sass-loader.

maximusnikulin commented 7 years ago

Did anyone solve this problem?

pgayvallet commented 7 years ago

Same issue here. @import makes sourcemap point to the parent file.

jhnns commented 7 years ago

I can confirm the problem. You can test that with https://github.com/jtangelder/sass-loader/pull/374/commits/ce198d169d4a1066d214d40ba88fb0b5029c0536 and npm run test-source-map.

Unfortunately, I don't know how to fix this since we don't actually mess with the source maps.

ggedde commented 7 years ago

@jhnns Could you explain more on "we don't actually mess with the source maps". Are you saying that sass-loader doesn't create the source maps. If so then what does and how? As mentioned running "node-sass" in the terminal the source maps are fine, but running it though sass-loader and webpack they are not.

Sorry I am not too familiar with sass-loader flow. Could someone explain the difference that running sass-loader through webpack has as compared to running node-sass through the terminal.

It almost seems like the scss file is converted to (nested, expanded, or compact) prior to the source map is being applied then the css is compressed.

Is there any way to test that sass-loader is getting the full un-compacted un-compressed scss files when creating the source mappings?

jhnns commented 7 years ago

We receive the source maps directly from node-sass. But since the source maps are also processed by the css-loader and other loaders on the way, it's hard to say what's going on. Maybe they are incompatible?

It would be good if you could investigate this. Build the smallest project possible that reproduces the error and inspect the source maps in the sass-loader and then in the css-loader. You can use the style-loader to apply the styles to the DOM. The style-loader uses a BLOB url to make the source maps available to the browser. It does not change the source maps anymore, so that should be fine.

alexander-akait commented 7 years ago

@woohling @maximusnikulin @wayofspark @ggedde The problem still exists? If yes please create minimal reproducible test repo

woohling commented 7 years ago

No longer working on the project with this issue. But I will find time to create a small demo to see if the problem still exists.

alexander-akait commented 7 years ago

@woohling just ping me when your do this :+1:

ggedde commented 7 years ago

Sorry @jhnns @evilebottnawi, I took a pause from this project. Nope, the issue still exists for me. I also just recently installed brand new ng-cli on a new laptop. Angular4.0 with CLI 1.0.2 which is using sass-loader 6.0.3

I created a small project and just had a few lines of scss code. It still pointed to the top parent node, but running node-sass works fine. Not sure what I can do to help further.

alexander-akait commented 7 years ago

@ggedde can your create minimal reproducible test repo?

ggedde commented 7 years ago

@evilebottnawi Yes, I can. I will let you know when I get that up.

In the meantime I did find that if I added outputStyle: 'compressed' to the sass-loader it now works for Chrome, but not FF.

So my guess is that css-loader is expecting the sass-loader to be compressed. So if sass-loader is not then you need to specify it. I am not sure how to have css-loader know what the format is. That way you wouldn't have to specify it.

So this may be an issue with css-loader and not sass-loader.

I will look at it again later tonight.

alexander-akait commented 7 years ago

@ggedde seems bugs not in sass-loader or css-loader (it makes no difference what we work on sass/scss/less and etc.). I think FF have bug, just ping me when test repo was created.

ggedde commented 7 years ago

Yes, FF has a bug, but Chrome doesn't work either unless you add outputStyle: 'compressed' to sass-loader. There may not be a bug with either, but there is definitely a configuration issue that is not well documented anywhere. Nor does anyone have a good grasp on how to configure css-loader with sass-loader to make the sourcemaps work properly. It would be great for us to figure it out then either someone from the sass-loader team or css-loader team right a blog post about it explaining the reasons why and how to properly configure webpack to output the correct sourcemaps. I will definitely do what I can to support it.

sandwich commented 7 years ago

I may be reading things incorrectly here, but I think y'all might be barking up the wrong tree if you're looking for the origin of the problem to be in sass-loader (assuming sass-loader is a webpack-specific thing).

See, I have this exact issue, of sourcemaps not referencing the right line if the @import is within a CSS selector. However, I'm using gulp—gulp-sass, gulp-sourcemaps, etc—not webpack.

Does this help any?

alexander-akait commented 7 years ago

@sandwich can your provide minimum reproducible test repo?

sandwich commented 7 years ago

Here ya go (not precisely minimum; I wanted it to be self-explanatory, too). Once extracted, run npm install, and then just gulp.

Reproducible in Chrome, Firefox, IE11, and Edge (i.e. it's not a browser issue).

Sourcemap Import Issue.zip

aszmyd commented 7 years ago

I've made an reproducible test repo using webpack - https://github.com/aszmyd/webpack-sass-loader-sourcemap-issue Just clone it, npm install, npm start and open browser at http://localhost:8080/

The issue is present there:

image

Even using outputStyle: 'compressed' its still broken.

alexander-akait commented 7 years ago

@aszmyd thanks, in near future i try to investigate this!

alexander-akait commented 7 years ago

@aszmyd invalid configuration. Fixed (invalid source map path):

const webpack = require('webpack');
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    context: path.resolve('src'),
    entry: './index.js',
    output: {
        filename: 'index.js',
        path: __dirname + '/dist'
    },
    devtool: 'source-map',
    module: {
        loaders: [
            {
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    use: [{
                        loader: 'css-loader',
                        options: {
                            sourceMap: true
                        }
                    }, {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true
                            // outputStyle: 'compressed'
                        }
                    }]
                })
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
            filename: 'styles/index.css'
        }),
        new HtmlWebpackPlugin(
            {
                filename: 'index.html',
                template: './index.html'
            })
    ]
};

In your test repo i have correct position. Can your provide more information your node version, npm, OS and etc?

alexander-akait commented 7 years ago

@sandwich your use gulp not webpack, how it is related to issue? Thanks! @woohling friendly ping @ggedde can your provide minimum reproducible test repo?

alexander-akait commented 7 years ago

@aszmyd reproduce, thanks, looking. Tomorrow I will write what was the problem

sandwich commented 7 years ago

@evilebottnawi Perhaps you missed my earlier post. I have the exact same issue, except I'm not using webpack, but gulp. Therefore, there's a decent chance that the issue is not in anything specifically related to webpack, but is rather in Sass or the Sass Sourcemaps code, since that's the only common denominator.

aszmyd commented 7 years ago

@sandwich i get Your point. I've tried to reproduce the same issue with using just node-sass but with no luck - test repo here.

sandwich commented 7 years ago

@aszmyd I have a test case as a zip up above, using gulp-sass and the like.

alexander-akait commented 7 years ago

@sandwich @aszmyd thanks for helping! @sandwich I'm inclined to assume that you are right, since we do not make any modifications with the source maps in the sass-loader

aszmyd commented 7 years ago

@sandwich i've checked You'r code and figured out that the part that is messing around with things is gulp-postcss together with autoprefixer. When i commented this one .pipe(postcss([ autoprefixer() ])) line in Your gulpfile, sourcemap points correctly to _typography.scss line 7.

So changed sass task that works:

gulp.task('sass', function()
{
    gutil.log("Now compiling all SCSS files...");
    return gulp.src('scss/**/*.scss')
        .pipe(plumber(plumberErrorHandler))
        .pipe(sourcemaps.init())
        .pipe(sass())
        // .pipe(postcss([ autoprefixer() ]))
        .pipe(sourcemaps.write('.').on('end', function()
            {
                gutil.log(" ...done generating sourcemaps.");
            })
        )
        .pipe(
            gulp.dest('public_html/css')
        )
        .pipe(browserSync.reload({
            stream: true
        }));
});

So my guess is that its more sass-loader/webpack related. @evilebottnawi were You able to figure out something from my reproducable repo?

alexander-akait commented 7 years ago

@aszmyd doing at this moment :smile:

alexander-akait commented 7 years ago

Btw seems bug did not located in sass-loader (https://github.com/sass/node-sass/issues/1206)

alexander-akait commented 7 years ago

@woohling @ggedde @folmert @wayofspark @sandwich @aszmyd won't fix in sass-loader :disappointed:

Information about why this happens: https://github.com/sass/libsass/issues/1747#issuecomment-159749530 and https://github.com/sass/libsass/issues/1747#issuecomment-160245200.

In short: browsers always show first selector in sequence nested selectors in source maps. I am closing this issue here because it is not related to sass-loader and we don't have time to fix this in other packages (libsass) which not related directly to webpack. Your can create new issue or write post in https://github.com/sass/libsass/issues/1747 if your think it is can be fixed.

Btw your can click in dev tools on property to move in right position in source maps.

aszmyd commented 7 years ago

@evilebottnawi im not sure this is the right decision. sass-loader is using node-sass. node-sass is:

a library that provides binding for Node.js to LibSass

And in one of my earlier posts i've created small repo that uses only node-sass and it works perfectly fine.

So question is - why pure node-sass is working properly but sass-loader that is using it underneath, is not?

alexander-akait commented 7 years ago

@aszmyd your can look loader code, we don't modify source map from node-sass. Just confirm:

  1. console.log(result.map.toString()) in https://github.com/webpack-contrib/sass-loader/blob/master/lib/loader.js#L60
  2. Output:
    {
        "version": 3,
        "file": "stdin.css",
        "sourceRoot": "/home/evilebottnawi/IdeaProjects/webpack-sass-loader-sourcemap-issue",
        "sources": [
                "stdin"
        ],
        "sourcesContent": [
                "html {\n    background: rgba(0, 0, 0, 0.7);\n}\n\nbody {\n\n    h1 {\n        color: white;\n    }\n}\n"
        ],
        "names": [],
        "mappings": "AAAA,AAAA,IAAI,CAAC;EACD,UAAU,EAAE,kBAAkB,GACjC;;AAED,AAEI,IAFA,CAEA,EAAE,CAAC;EACC,KAAK,EAAE,KAAK,GACf"
    }
  3. Open in chrome or mozilla http://127.0.0.1:8080/styles/index.css.map
  4. Output:
    {
    "version":3,
    "sources":["webpack:///./src/src/index.scss"],
    "names":[],
    "mappings":"AAAA;EACI,+BAA8B,EACjC;;AAED;EAGQ,aAAY,EACf",
    "file":"styles/index.css",
    "sourcesContent":["html {\n    background: rgba(0, 0, 0, 0.7);\n}\n\nbody {\n\n    h1 {\n        color: white;\n    }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/src/index.scss"],"sourceRoot":""}

    Seems something invalid in mappings, but it is not sass-loader, let's investigate this, thanks!

alexander-akait commented 7 years ago

@aszmyd something wrong in css-loader :disappointed:

  1. Add style-loader to webpack.config.js
    loaders: [
            {
                test: /\.scss$/,
                /*use: ExtractTextPlugin.extract({*/
                    use: [{
                        loader: 'style-loader',
                        options: {
                            sourceMap: true
                        }
                    }, {
                        loader: 'css-loader',
                        options: {
                            sourceMap: true
                        }
                    }, {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true
                            // outputStyle: 'compressed'
                        }
                    }]
               /* })*/
            }
        ]
  2. Open https://github.com/webpack-contrib/css-loader/blob/master/lib/loader.js#L114 (in node_modules/css-loader)
  3. Comment lines
    /*map = result.map;
            if(map.sources) {
                map.sources = map.sources.map(function(source) {
                    return source.split("!").pop().replace(/\\/g, '/');
                }, this);
                map.sourceRoot = "";
            }
            map.file = map.file.split("!").pop().replace(/\\/g, '/');*/
  4. Run npm run start and your can see that source map is valid
alexander-akait commented 7 years ago

Problem in postcss, which using in css-loader, I'll try to update postcss to the latest version in css-loader and see what happens

alexander-akait commented 7 years ago

Closing issue, because not related, sorry, but i can't do anything here :disappointed: Based issue: https://github.com/postcss/postcss/issues/926 Why it is happens: https://github.com/postcss/postcss/issues/926#issuecomment-294062807 Workaround: implement own loader which correct this behavior (difficult).

Maybe we can fix this in https://github.com/mozilla/source-map, your can create issue there with examples (prefer where only node-sass and postcss without webpack - easy debug), thanks!

ggedde commented 7 years ago

Hi @evilebottnawi , Thanks for all the hard work on this. I know you wanted this sooner, but here is my repo: https://github.com/ggedde/ngtest

It just uses AngularCLI (Requires Node and NPM)

git clone https://github.com/ggedde/ngtest.git
cd ngtest
npm install
npm run start

After NG finishes then Navigate your browser to http://localhost:4200 You will see that if you instead the <h1> that the color points to line 3 in the inspector, but is actually on line 9. This issue is on both Chorme and Firefox.

However, if you add:

outputStyle: 'compressed',

To the sass-loader [options] in "node_modules/@angular/cli/models/webpack-configs/styles.js" Then it works fine in Chrome, but not Firefox.

Hope this helps others. Thanks

alexander-akait commented 7 years ago

@ggedde thanks!

kevin074 commented 5 years ago
{
    test: /\.(css|scss)$/,
     use: [
         { loader:MiniCssExtractPlugin.loader },
         { loader: "css-loader",  options: { sourceMap: true } },
         { loader: "sass-loader", options: { sourceMap: true, outputStyle: 'compressed'} }
    ]
},

currently with this set up the source map would only be pretty darn close to the line in the scss file when I am inspecting through chrome console. Don't know if anyone else is seeing this as well.

    "webpack": "^4.20.2",
    "node-sass": "^4.10.0",
    "sass-loader": "^7.1.0",
    "css-loader": "^1.0.0",
    "mini-css-extract-plugin": "^0.4.3",
SweetsXob commented 5 years ago

This problem does not seem to be solved now. It seems less doesn't have this problem

fgblomqvist commented 4 years ago

I'm experiencing this issue now as well. Source map always end up referring to the top-level parent instead of to the actual line. Our setup is quite simple:

{
  test: /\.(s?css)$/,
  use: [{
    loader: MiniCssExtractPlugin.loader,
  }, {
    loader: 'css-loader',
    options: {
      sourceMap: true,
    },
  }, {
    loader: 'sass-loader',
    options: {
      sourceMap: true,
    },
  }]
},

Setting sassOptions: { outputStyle: 'compressed' } on sass-loader does not improve the situation. If I do that, the source map will even link to the wrong files (not just wrong lines).

Running node-sass using the CLI works well, it outputs correct source-maps for nested classes no matter which outputStyle is selected.

We're on pretty much the latest version of everything:

"css-loader": "^3.4.1",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"webpack": "^4.41.5",

Any ideas of why this could be happening? I could try to put together a demo repo if needed. Looks like @evilebottnawi had some insight on this before?

MichaelDWheeler commented 4 years ago

This resolved it for me:

 {
            test: /\.scss$/,
            use: [
                MiniCssExtractPlugin.loader,
                {
                  loader: "css-loader",
                  options: {
                    sourceMap: true,
                    url: false
                  }
                },
                {
                  loader: 'sass-loader',
                  options: {
                    sourceMap: true,
                    sassOptions: {
                      outputStyle: argv.mode === "production" ? "compressed" : "expanded",
                    }
                  }
                }
            ]
          },
          {
            test: /\.css$/,
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              "style-loader"
            ]
          },

I found it here: https://github.com/noreading/bootstrap4-webpack-boilerplate/blob/master/webpack.config.js

you may have to pass argv into module.exports like it is on the page I linked.