webpack-contrib / mini-css-extract-plugin

Lightweight CSS extraction plugin
MIT License
4.66k stars 388 forks source link

SourceMaps for imported SASS partials don't work #123

Closed gkatsanos closed 5 years ago

gkatsanos commented 6 years ago

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

alexander-akait commented 6 years ago

@gkatsanos looks like bug, feel free to investigate this and send PR :+1:

gkatsanos commented 6 years ago

let's see if others will pop up here to make sure it's not config specific. it's not blocking us right now but at least what I wanted is from someone to validate my configuration isn't messed up. specifically I had these questions:

and lastly, has anyone investigated sourcemaps in general? the only way to get them working is with devtool 'source-map' . No other option really seems to work. (and source-map isn't advised)

GodOfGrandeur commented 6 years ago

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

heyflo commented 6 years ago

I have the same issue. The sourcemaps for the SCSS files are lost.

davorpeic commented 6 years ago

Been trying to find a solution to this one for days, only main sass file is referenced. If I find some solution will let you know

alexander-akait commented 6 years ago

Somebody can create minimum reproducible test repo?

davorpeic commented 6 years ago

Ok, I can try doing it today

davorpeic commented 6 years ago

Ok, while recreating our repo to minimal reproducible case I got my sass to generate correct sourcemap pointing to imported sass files. So I assumed something is different. We had few warnings from node-sass as we were importing .css files directly from node_modules libraries, I temporarely removed that _plugins.scss file that handled those imports, and then I got my sourcemap to show correctly, after that I followed import method for css files mentioned here https://github.com/sass/node-sass/issues/2362#issuecomment-386259486 which then build all without errors and I got my sourcemap correctly built. I still need to find better way ti import my css files, but that is another issue.

cloakedninjas commented 6 years ago

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

JoshuaSoileau commented 6 years ago

+1

alexander-akait commented 6 years ago

PLEASE create minimum reproducible test repo

cloakedninjas commented 6 years ago

Here you go: https://github.com/cloakedninjas/mini-css-extract-plugin-sourcemap-bug

alexander-akait commented 6 years ago

@cloakedninjas invalid configuration, please use

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

Somebody other can create minimum reproducible test repo?

ezarowny commented 6 years ago

I'm running into this same problem. I have a main styles.scss that functions as an entry point for our SCSS.

If a style is coming from an imported scss file (prefixed by an underscores), it's mapped correctly back to its source file. If the style is actually in styles.scss, it links back to a concatenated file.

I then remembered that I was using postcss-loader and disabling that seemed to fix my problem. I'll play around with this a bit a more and try to determine what isn't playing well.

alexander-akait commented 6 years ago

@ezarowny PLEASE create minimum reproducible test repo

ezarowny commented 6 years ago

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

ezarowny commented 6 years ago

Well, I did make my test case and it's at https://github.com/ezarowny/loader-adventure. However, it's actually not causing the bug I'm seeing. I'm going to dig a bit into my vendors and see if any of them are causing any problems.

ezarowny commented 6 years ago

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.

ezarowny commented 6 years ago

@evilebottnawi do you want me to add bootstrap to the test case repo? Doing so will actually cause the sourcemap issue (if it's added to the top of styles.scss) but I feel doing so might be a bit out of scope for this project.

ezarowny commented 6 years ago

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.

CoolGoose commented 6 years ago

Same issue for me, working on a separate reproducible build since right now it's a bit hammered in an existing codebase.

Here's a link to my current webpack.config.js

The issue happens also if I am importing the scss files in a vue component (in that case the entrypoint vue component is the main source for all).

cloakedninjas commented 6 years ago

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 🤔

CoolGoose commented 6 years ago

@cloakedninjas i do have sourceMap: true for postcss-loader (same for resolve-url-loader and sass-loader and css-loader)

CoolGoose commented 6 years ago

Ok, this might be slightly silly, but I've noticed there's a resolve-url-loader version 3.0 that uses postcss. Switching to that makes it work-ish so in my case the issue was caused by resolve-url-loader not propagating the sourceMap correctly (although right now it seems that not all matches work perfectly). So i'm starting to think the problem isn't in the mini-css-extract-plugin itself, but in the whole flow of plugins over plugins over plugins :)

jasongilmour commented 5 years ago

+1

ankurarora commented 5 years ago

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 ?

alexander-akait commented 5 years ago

@ankurarora yep, in sass-loader we have some problem in source map due node-sass

alexander-akait commented 5 years ago

Somebody please create minimum reproducible test repo? Each +1/Same issue/Any updates will be ignore and marked as abuse because it is clogs thread.

bramvdpluijm commented 5 years ago

Same issue here. I'm using this config and order:

{ test:/\.(s*)css$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: true, importLoaders: 1 } }, { loader: 'postcss-loader', options: { config: { path: './config' }, sourceMap: true } }, { loader: 'sass-loader', options: { sourceMap: true } }, ] },

And the plugin definition looks like this:

plugins: [ new LoadablePlugin(), new MiniCssExtractPlugin({ filename: devMode ? 'dist/[name].css' : 'dist/[name].[hash].css', }), ],

octoshrimpy commented 5 years ago

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:

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.

alexander-akait commented 5 years ago

Please create minimum reproducible test repo, otherwise issue was closed to avoid spamming (many example above has invalid copnfiguration and/or use old version of loaders/plugins/webpack)

octoshrimpy commented 5 years ago

@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.

alexander-akait commented 5 years ago

@octoshrimpy Yep, as i said above node-sass have some problems with source map and we can't do something on our side to fix it.

Closing issue, feel free to feedback.

amarraja commented 5 years ago

@octoshrimpy thanks for looking into this. You can pass the sourceMapEmbed property directly in your webpack config, rather than using a sub-shell. This worked for me:

{
    loader: "sass-loader",
    options: {
        sourceMap: true,
        sourceMapEmbed: true,
        includePaths: [
            path.resolve(__dirname, "scss")
        ]
    }
}
luxueyan commented 5 years ago

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

Antoinebr commented 5 years ago

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 ⚠️
                        }
                    },
rublev commented 5 years ago

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!