nDmitry / grunt-autoprefixer

Parse CSS and add vendor-prefixed CSS properties using the Can I Use database. Based on Autoprefixer.
MIT License
794 stars 60 forks source link

Source maps referring to complied css instead of SASS files #88

Open joelworsham opened 9 years ago

joelworsham commented 9 years ago

I use grunt-sass combined with autoprefixer.

When autoprefixer runs after the sass compiles, it creates the source map just fine, but when I view inspector, the source map is referring to the compiled sass file instead of the source sass itself

nDmitry commented 9 years ago

Sounds like Autoprefixer can't find previous source maps from grunt-sass. Could you post your options for grunt-sass and grunt-autoprefixer and your file structure please?

joelworsham commented 9 years ago

File Structure:

style.css
style.css.map
assets/sass/main.scss
assets/sass/_*.scss
assets/sass/admin/admin.scss
assets/sass/admin/_*.scss
...

// SASS
sass: {
    dist: {
        options: {
            sourceMap: true,
            outputStyle: 'compressed'
        },
        files: {
            'style.css': 'assets/sass/main.scss'
        }
    },
    admin: {
        options: {
            sourceMap: true,
            outputStyle: 'compressed'
        },
        files: {
            'admin.css': 'assets/sass/admin/admin.scss'
        }
    }
},

// Auto prefix our CSS with vendor prefixes
autoprefixer: {
    options: {
        browsers: ['last 2 version'],
        map: true
    },
    dist: {
        src: 'style.css'
    },
    admin: {
        src: 'admin.css'
    }
},

...
ghost commented 9 years ago

I came here to report the same problem. Here's my file structure: styles.css styles.css.map styles/sass/styles.scss styles/sass/_*.scss

And my gruntfile sass and autoprefixer setup:

...

sass: {
        dist: {
            options: {
                sourceMap: true
            },
            files: {
                'styles/styles.css': 'styles/sass/styles.scss'
            }
        }
    },
    autoprefixer: {
        sourcemap: {
            options: {
                map: true
            },
            src: 'styles/styles.css',
                    dest: 'styles/styles.css'
        },
    },

...
martinpesout commented 9 years ago

I have exactly the same problem. And both sass and autoprefixer are configured to use sourcemaps.

It seems that only few selectors are mapped fine to SCSS and rest of selectors are reffering to compiled CSS.

Is it possible then BEM methodology for can broke it? Because I'm using syntax like this

.main-banner {
    &__img {
        }
}
nDmitry commented 9 years ago

I couldn't reproduce the issue. Here is my setup: http://cl.ly/001w090D1f33/ga-88.zip

cd into downloaded directory and run grunt sass and grunt autoprefixer, you'll get correct maps. So make sure you're using grunt-autprefixer 2.1.0 in your projects and let me know if you can make that setup produce a map with incorrect sources array inside.

martinpesout commented 9 years ago

I had older grunt-autoprefixer 2.0.0. So I did update and now I'm running on 2.2.0. But problem is still here.

Let me show you my testing project (it's blank templated generated by Yeoman).

Autoprefixer is included in Gruntfile by default. You can see that some CSS selectors are referring to complied css. Only some a few definitions are referring to SCSS file (_type.scss)

snimek obrazovky 2015-01-17 v 9 23 32

If I remove whole autoprefixer definition form my Gruntfile and restart grunt task, I will see this result (SourceMaps are ok):

snimek obrazovky 2015-01-17 v 9 23 58

nDmitry commented 9 years ago

Ok I see now, in the map from libsass we have:

"file": "app.css", "sources":["app.scss","../bower_components/foundation/scss/normalize.scss",[...]]

And then after Autoprefixer run:

"file": "app.css", "sources":["app.css","../bower_components/foundation/scss/normalize.scss",[...]]

So app.scss becomes app.css though it shouldn't.

@ai any ideas why this is happening? PostCSS gets map: true option in this case.

ai commented 9 years ago

I think we has some CSS path problem.

This can be happend when by some reasom app.css from Sass map file and app.css from from option was converted to different absoulte path in postcss/map-generator.

ffigiel commented 9 years ago

I'm experiencing the same issue. Any progress so far?

LostSenSS commented 9 years ago

I had this issue too. After installation of old version grunt-sass (0.16.1 instead 0.18.0) everything worked. It's strange, because sourcemap from grunt-sass 0.18.0 worked wIthout autoprefixer.

nDmitry commented 9 years ago

@LostSenSS thanks, this helped.

Looks like everybody here is using grunt-sass then. I investigated the difference between 0.16.1 and 0.18.0 and also grunt-contrib-sass using the file structure above and here it is:

0.16.1

"sources": ["assets\/sass\/main.scss","assets\/sass\/_test.scss"],

0.18.0

"sources": [
    "main.scss",
    "_test.scss"
],

contrib

"sources": ["assets/sass/_test.scss"],

As you can see either grunt-sass or node-sass has dropped the relative paths to the sources for some reason and Autoprefixer cannot find them and update.

I didn't try it myself, but I guess enabling inline sourcemaps (sourceMapEmbed: true) or including sources contents (sourceMapContents: true) will do.

fboes commented 9 years ago

I am having the same problem:

package.json:

"devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-uglify": "^0.8.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-jslint": "^1.1.12",
    "grunt-contrib-sass": "^0.9.2",
    "jit-grunt": "^0.9.1",
    "grunt-autoprefixer": "^2.2.0",
    "grunt-shell": "^1.1.2",
    "grunt-text-replace": "^0.4.0"
  },

Gruntfile.js

        sass: {
            build: {
                options: {
                    style: 'compact'
                },
                files: [{
                    expand: true,
                    cwd: '<%= dirs.root %>sass',
                    src: ['*.scss'],
                    dest: '<%= dirs.web %>css',
                    ext: '.css'
                }]
            }
        },
        autoprefixer: {
            build: {
                expand: true,
                flatten: true,
                options: {
                    map: true
                },
                src: '<%= dirs.web %>css/styles.css',
                dest: '<%= dirs.web %>css/'
            }
        },

Would it solve the problem if there was an option telling autoprefixer to keep the sourcemap-comment at the end of the file and do not do anything with the comment or the sourcemap?

qwo commented 9 years ago

a hack but i fixed my same issue by compiling my sass to css with a dist of "prestyles.css" and then ran the autoprefixer on the sass dist to create my final compile to "styles.css"

this does create two compileds css files and maps but i was having the same issue and sunk too much time on this to get scss mappings with auto prefixing.

martinpesout commented 9 years ago

So what is the result of this research? It will be better to use grunt-contrib-sass rather than grunt-sass to prevent this problems? right? :)

fboes commented 9 years ago

Sorry, I am using grunt-contrib-sassand having the same problem. So switching from grunt-sass to grunt-contrib-sass will not help you. ;)

ai commented 9 years ago

BTW, PostCSS has many plugins. You can do nested, variables and mixins by pure PostCSS (Autoprefixer is just a PostCSS plugin). So you can replace Sass and have perfect source map and fastest gulp (PostCSS is 3 times faster that libsass).

JacobDorman commented 9 years ago

Check that there aren't any unicode characters in your sass.

libsass adds @charset "UTF-8"; to the css, which causes autoprefixer to output a broken sourcemap.

without @charset

{
  "version": 3,
  "sources": ["../app.scss"],
  "names": [],
  "mappings": "AAAA;EACc,qBAAA,EAAA;EACF;IACR,kBAAY,EAAA;EAGhB;IACI,kBAAY,EAAA",
  "file": "app.css"
}

with @charset

{
  "version": 3,
  "sources": [
    "../app.scss",
    "pre.css"
  ],
  "names": [],
  "mappings": "AAAA,kBAAA;ACCA;EDCK,qBAAO,EAAA;ECCV;IDEO,kBAAA,EAAA;ECAP;IACE,kBAAiB,EAAE",
  "file": "app.css"
}

tested with grunt-sass@0.18.1 grunt-postcss@0.3.0 with autoprefixer-core@5.1.8

fboes commented 9 years ago

Hm, by removing all UTF-8 references and verifying that there is no UTF-8 comment at the beginning of my CSS files, I still have the wrong line numbers. They are off by some 5-10 lines (which ist better than nothing, but still)

Setup: "grunt-contrib-sass": "^0.9.2","grunt-autoprefixer": "^2.2.0"

@JacobDorman: sorry ;)

JacobDorman commented 9 years ago

Ahh, the plot thickens :)

We might be dealing with multiple issues. @charset was definitely causing my problem. Removing the character fixes the sourcemaps.

Test repo here: https://github.com/JacobDorman/libsass-autoprefixer-test/ I'll continue this specific issue over at https://github.com/postcss/autoprefixer/issues/430

joelworsham commented 9 years ago

Here's something interesting. I noticed that if I ran my grunt-sass task, the line references from the map were incorrect. Opening the map file, I noticed a bunch of extra semicolons... If I manually removed them, the references were fixed.

So, just to test it out, I manually removed those semicolons and then re-ran autoprefixer. The problem was fixed! So the stem of this issue for me is in grunt-sass, but moreso, Libsass itself. I've opened a ticket there we can follow.

sass/libsass#1052

digitalCitizen commented 9 years ago

I'm working with Gulp, but I'm having the exact same issue as being described here. The styles.map.css looks fine, except that it only shows the first module, and then loads the generated styles.css file. I'm using gulp-sass with autoprefixer.

I'm not sure how to solve this, as I am unfamiliar with gulp/sass. I've tried the solutions in this thread (the ones that I understood) but nothing works so far.

digitalCitizen commented 9 years ago

For me, disabling/downgrading Browserify solved the issue... are you using this plugin? Does removing it help in any way?

tomslominski commented 9 years ago

I think I'm also having this issue. The map comment is at the end of my generated .css file, autoprefixer says the map file is generated, and yet no browser displays line references at all.

Interestingly, if I have my grunt config like this:

autoprefixer: {
    options: {
        map: {
            inline: false,
            sourcesContent: false
        }
    },
        src: 'styles/style.css'
},

It writes the out file to /src and /src.map. If I also add a dest, it saves /src, /src.map, /dest, /dest.map. This is all as opposed to /styles/style.css and /styles/style.css.map, where you would expect it to save. BUT, if it saves the file as /src, the sourcemap does work.

tannerhodges commented 9 years ago

Had this issue too but upgrading to grunt-postcss fixed.

The note for "How to migrate from grunt-autoprefixer?" made it super easy.

Shoutout to @nDmitry for making such a seamless transition. Really appreciate it!

martinpesout commented 9 years ago

But there is one disadvantage. It's not possible to easy migrate from SCSS to PostCSS just with switching of preprocessor to postprocessor. Both technologies need different approach from the beginning of whole frontend development. If I have big project, it takes some time to rewrite my code.

Good info is, that I'll just use PostCSS in future for another new project

tannerhodges commented 9 years ago

@martinpesout I thought that at first too, but it's not true. For example, I use Compass on all of my projects. Then I just have a Grunt task to run PostCSS on top of it:

grunt.registerTask('build-css', [
    'compass',
    'postcss'
]);

I just add that to grunt watch and it runs whenever I update my SCSS files.

If you want, I can throw together a repo to give you the full picture. But yeah, PostCSS for me is just icing on my SCSS cake.

ihorzenich commented 9 years ago

I also have this problem if I add material.min.css from Google MDL (http://www.getmdl.io/started/index.html). I read about promblem with @charset "utf-8" and delete it almost, but bug still present.

martinpesout commented 9 years ago

@tannerhodges I never though about this way of usage. I was thinking only about writing everything in preprocessor or only in postprocessor. Combining both together can be also useful :+1:

icarlosmendez commented 9 years ago

I found this thread while looking for an answer to the same problem. I am using gulp and have my setup where I have different levels of scss/css manipulation. The most basic is to convert the scss to css for use in the browser during routine development. Second I use autoprefixer to prepare for cross-browser compatability. And finally I use a minification plugin to prep for deployment.

I was running sourcemaps on both my first and second stages of development and when reviewing the error messages I noticed that autoprefixer was looking at the previous map (which some posters have referred to). By commenting out the creation of the map in the first stage, I realized I could avoid the error.

And so finally, I simply added a delete statement to my second stage to dump the first map before running autoprefixer and now my flow is flowing again. This is acceptable because what ever level of dev or testing I am at I only need the map relating to that stage so any previous ones would be useless later on. Hopes this helps somebody out.

Here is my code so folks can review for clarity: // SASS gulp.task('compileSass', function() { return gulp.src('app/scss/main.scss') .pipe(maps.init()) .pipe(sass({ errLogToConsole: true })) .pipe(rename('main.css')) .pipe(maps.write('./')) .pipe(gulp.dest('app/css')); });

gulp.task('prefix', ['compileSass'], function() { del(['app/css/main.css.map']); return gulp.src('app/css/main.css') .pipe(maps.init()) .pipe(autoprefixer({ browsers: ['last 2 versions'], cascade: true, })) .pipe(maps.write('./')) .pipe(gulp.dest('app/css')); });

gulp.task('cssmin', ['prefix'], function() { return gulp.src('app/css/main.css') .pipe(cssmin()) .pipe(rename('main.min.css')) .pipe(gulp.dest('app/css')) })

gulp.task('devStyles', ['cssmin'], function() {

})

kapena commented 8 years ago

@icarlosmendez thank you for your explanation on how your gulpfile.js is working to build out your project. I integrated your solution into my build however decided to bundle it up a little more. Here's my solution.

I have a task called proj1_styles that performs the the scss compiling, cssmin, file renaming, and sourcemaps. proj1_styles is sent to my default task.

Then I have the task autoprefix_proj1 which makes a call to proj1_styles task. Once proj1_styles finishes running autoprefix_proj1 performs the deletion of the last sourcemap file that was created then and adds a new sourcemap from the most current css and runs the autoprefixer.

I don't have autopreix_proj1 inside my default task. So I when I want the most current sourcemap file and autoprefixed css I just run gulp autoprefix_proj1 and it's all taken care of.

Hope this helps someone else out.

// prefixer and sourcemaps proj1
gulp.task('autoprefix_proj1',['proj1_styles'],function () {
    del(['./site/css/main.css.map']);
    return gulp.src('./site/indiv_project_pages/proj1/css/proj1_main.css')
        .pipe(sourcemaps.init())
        .pipe(postcss([ autoprefixer({ browsers: ['> 1%','last 2 versions'] }) ]))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(paths.project_pages_dest.proj1_dest.styles_proj1));
});

// Styles task for proj1
gulp.task('proj1_styles',function(){
    // source to project 1 scss
    return gulp.src(paths.source.project_pgs_src.proj_1.styles_proj1)
    .pipe(plumber({
        // plumber finds errors in stream
        errorHandler: onError}))
    .pipe(sourcemaps.init()) // source maps
    .pipe(sass())
    .pipe(gulp.dest(paths.project_pages_dest.proj1_dest.styles_proj1))
    .pipe(cssmin()) // min css
    .pipe(rename({ // rename file to site.min.css
        suffix:'.min'
    }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest(paths.project_pages_dest.proj1_dest.styles_proj1))
    .pipe(notify({ message: 'proj1_styles task finished' }))
    .pipe(browserSync.stream());
});