sindresorhus / gulp-autoprefixer

Prefix CSS
MIT License
694 stars 50 forks source link

.css file listed in source maps when using LESS #10

Closed jupl closed 9 years ago

jupl commented 10 years ago

If I run something along the lines of:

gulp.src('src/less/*.less')
  .pipe(sourcemaps.init())
  .pipe(less())
  .pipe(autoprefixer())
  .pipe(sourcemaps.write())
  .pipe('dist');

With a file src/less/index.less, in the source maps it shows an index.less file as expected, but also in the same place a index.css file also appears and in DevTools it says it does not exist. If I don't use Autoprefixer the extra index.css file does not appear in source maps.

sindresorhus commented 9 years ago

Does this still happen with the latest version?

themouette commented 9 years ago

I have the same issue using gulp-sass. Apparently there is no matching issue in autoprefixer, but I might have missed something.

ghost commented 9 years ago

Happens for me too with the latest version with gulp-ruby-sass.

Asked about it in gulp-sourcemaps already: https://github.com/floridoo/gulp-sourcemaps/issues/76

thibaultcha commented 9 years ago

Having a similar issue here. It seems to me I can't force gulp-autoprefixer to send false here?

jupl commented 9 years ago

Also, another issue that occurs is that any other files that have been referenced with @import in Sass are gone with Autoprefixer when viewing sources.

polarathene commented 9 years ago

I have been messing around with sourcemaps recently with gulp and trying to pass my compiled .scss to other gulp plugins like gulp-autoprefixer. I've had some success so this might help you :)

@jupl I haven't tried with LESS, though my code examples might help? You could also see if using two tasks or output css/sourcemaps helps instead of overriding the current. I know previously with gulp-sass something like this worked:

gulp.src('src/less/*.less')
  .pipe(sourcemaps.init())
  .pipe(less())
  .pipe(sourcemaps.write())
  .pipe(sourcemaps.init({loadMaps:true}))
  .pipe(autoprefixer())
  .pipe(sourcemaps.write('.', {includeContent:false, sourceRoot:'.'}))
  .pipe('dist');

My folder structure for below examples: project/

gulp-sass

gulp-sass was updated today from 1.2.4 to 1.3.1, some bug fixes and update to node-sass v2 support. This is important, as at least for me the other day the sourcemap mappings being produced were incorrect, they're still not perfect, but much more usable now.

npm install gulp-sass does not include node-sass in it's _nodemodules if you have done npm install node-sass prior. Make sure your node-sass is also up to date if you run into any problems.

// node-sass v2.0.0-beta
var gulp = require('gulp'); // v3.8.10
var sass = require('gulp-sass'); // v1.3.1
var sourcemaps = require('gulp-sourcemaps'); // v1.3.0
var autoprefixer = require('gulp-autoprefixer'); // v2.0.0

// Compiles .css file with inline sourcemap with embedded sources
gulp.task('gsass', function(){
    gulp.src('scss/*.scss')
        .pipe(sourcemaps.init())
        .pipe(sass())
        .pipe(autoprefixer({browsers: ['last 2 version']}))
        .pipe(sourcemaps.write())
        //.pipe(sourcemaps.write({includeContent:false, sourceRoot:'../../scss/'})) // inline sourcemap without embedded sources
        //.pipe(sourcemaps.write('.', {includeContent:false, sourceRoot:'../../scss/'})) // external sourcemap without embedded sources, remove options to embed.
        .pipe(gulp.dest('./build/css/'));
});

Prior to the gulp-sass update I built libsass/node-sass from github sources as NPM releases had the mapping problem. I've compared the results with the gulp-sass update, slightly different mappings. Github libsass/node-sass and with autoprefixer

With gulp-sass update and with autoprefixer.

Differences with the mappings are mostly consistency. When autoprefixed, gulp-sass matches the color vars to their partial, the last } matches the var $value partial instead of just the ; which shouldn't be matching to the partial. gulp-sass also maps filter/sepia() differently based on source style(single vs multi-line), evident by hovering over the class names and -webkit-filter as well as the } matching between main.scss and partials.

The recent build from github version matches both } to ; next to the previous partial match, however the variables themselves are matched to their line in main.scss instead of the partial. The sepia() filter is mapped/split a little differently but matches better.

gulp-ruby-sass

If you want to use ruby, the current sourcemap support is buggy. Slightly better with the npm install gulp-ruby-sass@1.0.0-alpha version though which I'll show here:

var gulp = require('gulp');  // v3.8.10
var rsass = require('gulp-ruby-sass'); // v1.0.0-alpha
var sourcemaps = require('gulp-sourcemaps'); // v1.3.0
var autoprefixer = require('gulp-autoprefixer'); // v2.0.0

gulp.task('grsass', function(){
    var scss_filename = 'scss/'; // no globbing support yet
    rsass(scss_filename, {sourcemap:true}) // note begins with gulp-ruby-sass, not gulp.src or anything else, triggers sourcemaps.init() internally
        .pipe(autoprefixer({browsers: ['last 2 version']}))
        .pipe(sourcemaps.write())
        .pipe(gulp.dest('./build/css/'));
});

At least with my own experiences, this won't work, nothing is placed in sourcesContent, and the file path is incorrect (apparently a Windows issue). So I end up with this broken sourcemap:

{  
   "version":3,
   "sources":[  
      "../../../../C:/Development/Web/Test-Gulp/scss/main.scss",
      "../../../../C:/Development/Web/Test-Gulp/scss/_config.scss",
      "../../../../C:/Development/Web/Test-Gulp/scss/test/_num.scss"
   ],
   "names":[  

   ],
   "mappings":"AAGA;EAAW,4BAAqB;UAArB,oBAAqB;EAAE,gBCHpB,EAAA;;ADKd;EACE,4BAAqB;UAArB,oBAAqB;EACrB,aCNQ;EDOR,cERS,EAAA",
   "file":"main.css",
   "sourcesContent":[  
      null,
      null,
      null
   ],
   "sourceRoot":"/source/"
}

If you don't have the file path issue, then you can still inline the sourcemap into your .css file with references to the external .scss sources. I've tested this with one gulp task to run gulp-ruby-sass@1.0.0-alpha, after manually fixing the file paths, then a 2nd gulp task to run gulp-autoprefixer on it. Works fine as can be seen here.

Until gulp-ruby-sass embeds sourcesContent when doing an inline map you can try this(might work):

gulp.task('grsass', function(){
    var scss_filename = 'scss/'; // no globbing support yet
    rsass(scss_filename, {sourcemap:true}) // note begins with gulp-ruby-sass, not gulp.src or anything else, triggers sourcemaps.init() internally
        .pipe(autoprefixer({browsers: ['last 2 version']}))
        .pipe(sourcemaps.write({includeContent:false, sourceRoot:'../../scss/'}))
        .pipe(gulp.dest('./build/css/'));
});
jupl commented 9 years ago

For LESS, I just ended up dropping gulp-autoprefixer for less-plugin-autoprefix. I'm checking out the writeup @polarathene for Sass later.

mnpenner commented 9 years ago

I'm experiencing this issue too. My pipeline looks like this:

gulp.task('styles', function () {
    return gulp.src(styles, {base: '.'})
        .pipe(plumber())
        .pipe(sourcemaps.init({
            loadMaps: false,
            debug: debug,
        }))
        .pipe(gulpif(/\.less$/,less({
            strictMath: true,
            strictUnits: true,
        })))
        .pipe(gulpif(debug, wrapper({
            header: fileHeader,
        })))
        .pipe(concat('main.css'))
        .pipe(autoprefixer({
            browsers: ['> 1%', 'last 2 versions', 'Firefox ESR', 'Opera 12.1', 'ie >= 7'],
            cascade: false // don't waste time on this
        }))
        .pipe(gulpif(!debug, minifyCss({
            compatibility: 'ie7',
        })))
        .pipe(sourcemaps.write('.', {
            includeContent: true,
            sourceRoot: '/',
        }))
        .pipe(plumber.stop())
        .pipe(gulp.dest('www/css'))
});

If I remove autoprefixer from the mix, my sourcemaps come out fine. If I leave it in there, it references main.css (the output file) in a few places.


I've just tried less-plugin-clean-css, but it has the same issue, so I'm guessing this is an upstream issue with Autoprefixer.


gulp-postcss has the same issue too.

.pipe(postcss([
    autoprefixer({
        browsers: ['> 1%', 'last 2 versions', 'Firefox ESR', 'Opera 12.1', 'ie >= 7'],
        cascade: false 
    })
]))
polarathene commented 9 years ago

@mnpenner That issue doesn't exist with the Sass plugins when using gulp-sourcemaps anymore. It could be an issue with your other plugins not supporting gulp-sourcemaps properly. Try doing:

.pipe(sourcemaps.write())
.pipe(sourcemaps.init({loadMaps:true})

Just before autoprefixer. This will write the sourcemap inline with the concatenated main.css file and then load it on the 2nd init of sourcemaps.

I'm not sure but I think the issue you're having might be that you are writing an external sourcemap and providing a sourceRoot, but then embedding the css into the sourcemap. Since sourceRoot won't be /source/ (default) it won't reference the embedded content, instead it'll look for the css specified in the sources property and prefix them with the relative path from the sourcemap file specified in sourceRoot.

If you're still having no luck after trying both of those, verify that your sourcemaps are working correctly without autoprefixer, check that the css links to the correct line in the original source files. If the mapping is wrong, then it's not autoprefixer but some other plugin that is not compatible with gulp-sourcemaps yet. In which case, create a smaller simplified task that isolates/breaks down the task and test each new plugin as you add it to the task to see where it breaks. In my experience autoprefixer has been blamed in the past when it was working correctly but receiving a bad sourcemap to work with which was the real problem.

petermac- commented 9 years ago

I'm having a similar issue on Windows 8.1 x64 with gulp-sass, gulp-sourcemaps, and gulp-autoprefixer. When I remove gulp-autoprefixer the sourcemaps work fine. I set debug:true for gulp-sourcemaps and no errors were reported.

var cssTasks = function(filename) {
  return lazypipe()
    .pipe($.plumber)
    .pipe(function() {
      return $.if(enabled.maps, $.sourcemaps.init());
    })
      .pipe(function() {
        return $.if('*.less', $.less().on('error', function(err) {
          console.warn(err.message);
        }));
      })
      .pipe(function() {
        return $.if('*.scss', $.sass({
          outputStyle: 'nested', // libsass doesn't support expanded yet
          precision: 10,
          onError: console.error.bind(console, 'Sass error:')
        }));
      })
      .pipe($.concat, filename)
      .pipe($.autoprefixer, {
        browsers: [
          'last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12'
        ],
      })
    .pipe(function() {
      return $.if(enabled.rev, $.rev());
    })
    .pipe(function() {
      return $.if(enabled.maps, $.sourcemaps.write('.', {debug:true, includeContent:false, sourceRoot:'/app/themes/sage/assets/styles'})) // external sourcemap without embedded sources, remove options to embed.
    })();
};

Portion of main.css.map

{"version":3,"sources":["main.css","vendor/_normalize.scss"...
"file":"main.css","sourceRoot":"/app/themes/sage/assets/styles"}

I also tried using the suggested fix from @polarathene:

var cssTasks = function(filename) {
  return lazypipe()
    .pipe($.plumber)
    .pipe(function() {
      return $.if(enabled.maps, $.sourcemaps.init());
    })
      .pipe(function() {
        return $.if('*.less', $.less().on('error', function(err) {
          console.warn(err.message);
        }));
      })
      .pipe(function() {
        return $.if('*.scss', $.sass({
          outputStyle: 'nested', // libsass doesn't support expanded yet
          precision: 10,
          onError: console.error.bind(console, 'Sass error:')
        }));
      })
      .pipe($.concat, filename)
      .pipe($.sourcemaps.write, {debug:true})
      .pipe($.sourcemaps.init, {loadMaps:true})
      .pipe($.autoprefixer, {
        browsers: [
          'last 2 versions', 'ie 8', 'ie 9', 'android 2.3', 'android 4', 'opera 12'
        ],
      })
    .pipe(function() {
      return $.if(enabled.rev, $.rev());
    })
    .pipe(function() {
      return $.if(enabled.maps, $.sourcemaps.write('.', {debug:true, includeContent:false, sourceRoot:'/app/themes/sage/assets/styles'})) // external sourcemap without embedded sources, remove options to embed.
    })();
};

Which resulted in the following errors:

gulp-sourcemap-write: No source content for "vendor/_normalize.scss". Loading from file.
gulp-sourcemap-write: No source content for "vendor/neat/grid/_box-sizing.scss". Loading from file.
gulp-sourcemap-write: No source content for "vendor/bourbon/addons/_prefixer.scss". Loading from file.
gulp-sourcemap-write: No source content for "vendor/_prism.scss". Loading from file.
gulp-sourcemap-write: No source content for "_toolkit.scss". Loading from file.
...

Portion of main.css.map

{"version":3,"sources":["main.css","/source/vendor/_normalize.scss"...
"file":"main.css","sourceRoot":"/app/themes/sage/assets/styles"}

The mappings appear to be accurate without autoprefixer. Any ideas on what's causing the issue?

polarathene commented 9 years ago

@petermac- From memory, sourceRoot is relative path from your sourcemap to your source files. /app/themes/sage/assets/styles suggests that the sourcemap is in the parent directory of app. Which I'm guessing isn't the case. Use ../ to move up a folder as needed, eg if the location of sourcemap was in /app/themes/src/css you could use ../../sage/assets/styles.

If you are embedding the source files into the sourcemap, your sourceRoot should be /source/ which is the default. sourcemaps.write() with no params will embed the source files as well as inline the sourcemap into your css file in base64. sourcemaps.init({loadMaps:true}) should read embedded+inline fine. If you need external source files being referenced then include the option includeContent:false and provide the correct sourceRoot, I'm not sure how this works via a stream if it's not written & loaded from disk(due to the relative sourceRoot path).

Your issue does seem to be the sourceRoot you set in both examples though. I'd make sure that your sourcemap without autoprefixer is correctly mapping to the right files and lines before blaming autoprefixer. There is a handy visualization tool you can use here

If you're still having trouble, the best way to tackle it is isolation. Create some dummy .scss like in the examples I've provided, compile it with sourcemaps, then add in autoprefixer. If just those two are causing problems when autoprefixer is added then you can share that with us to take a look on our systems, simplifying the problem will greatly help towards pinpointing what's causing it. If it turns out that works fine, then add in another step to the test task, such as concat. If that causes a problem try again without autoprefixer and verify mappings are correct.

In addition to all that be sure that your node_modules are up to date. That can make all the difference, gulp-sass depends on node-sass which uses libsass, libsass was outputting invalid mappings a month ago.

boogerlad commented 9 years ago

I'm having the same issue still with the latest modules installed.

gulp.src(...)
.pipe(sourcemaps.init())
.pipe(less())
.pipe(autoprefixer())
.pipe(concat('yebrethang.css'))
.pipe(minify())
.pipe(sourcemaps.write('../maps', {debug: true}))
.pipe(gulp.dest('.tmp/public/css'));

This is what I get on the console.

gulp-sourcemap-write: No source content for "normalize.less". Loading from file.
gulp-sourcemap-write: No source content for "yebrithang.css". Loading from file.
gulp-sourcemap-write: source file not found: /root/cutequickposweb/bower_components/bootstrap/less/yebrithang.css
gulp-sourcemap-write: No source content for "print.less". Loading from file.
gulp-sourcemap-write: No source content for "glyphicons.less". Loading from file.
gulp-sourcemap-write: No source content for "scaffolding.less". Loading from file.

Of course source file is not found... It shouldn't exist in the first place! Commenting out autoprefixer fixes it.

I've also tested using the less plugin. It is surely an upstream bug. There is even a hack in this module on line 99 in index.js. https://github.com/postcss/autoprefixer-core/issues/27

polarathene commented 9 years ago

@boogerlad Just so you're aware, the autoprefixer line you provided doesn't have a closing ).

I've not used less but autoprefixer works fine with sourcemaps using sass, so if there is an issue it's likely less.

boogerlad commented 9 years ago

Thanks for correcting me. It was just psuedo code since the actual code is a bit more complex. You are correct that the issue is with less. https://github.com/less/less.js/issues/2413

mnpenner commented 9 years ago

@polarathene

I tried adding

.pipe(sourcemaps.write())
.pipe(sourcemaps.init({loadMaps:true}))

There was no change in output.

Tried removing the sourceRoot option too. No change either.

verify that your sourcemaps are working correctly without autoprefixer, check that the css links to the correct line in the original source files.

Works fine without autoprefixer. When I click the source link in Chrome DevTools it does take me to the correct line, although it takes me to the parent selector in the case of nested selectors in LESS.

polarathene commented 9 years ago

@mnpenner It seems like it's a bug with LESS sourcemaps not mapping }? I don't work with LESS so I can't confirm if it's LESS or autoprefixer is at fault. Considering Sass works fine with autoprefixer I think the issue might be LESS. Try a simple LESS example without autoprefixer on this: http://sokra.github.io/source-map-visualization/#custom Then save the link and share it, as well as another when you use autoprefixer sourcemap if possible.

jonrimmer commented 9 years ago

I am having the same problem with SASS.

I am using the latest version of gulp-sass and gulp-autoprefixer, as follows:

gulp.src('app.scss')
  gulp.pipe(sourcemaps.init())
  gulp.pipe(sass())
  gulp.pipe(prefix("last 2 versions"))
  gulp.pipe(sourcemaps.write())
gulp.pipe(gulp.dest('./build'))

If I comment out the prefix line, then the generated source map is valid, but if I include it, then the maps are invalid, and do not work in the browser.

I tried adding...

  gulp.pipe(sourcemaps.write())
  gulp.pipe(sourcemaps.init({loadMaps:true})

...and I got the following error:

Error: "/components/deploy/deployer.scss" is not in the SourceMap.
at SourceMapConsumer_sourceContentFor [as sourceContentFor] (/gui/client/node_modules/gulp-autoprefixer/node_modules/vinyl-sourcemaps-apply/node_modules/source-map/lib/source-map/source-map-consumer.js:415:13)
    at SourceMapGenerator.<anonymous> (/gui/client/node_modules/gulp-autoprefixer/node_modules/vinyl-sourcemaps-apply/node_modules/source-map/lib/source-map/source-map-generator.js:233:42)
    at Array.forEach (native)
    at SourceMapGenerator_applySourceMap [as applySourceMap] (/gui/client/node_modules/gulp-autoprefixer/node_modules/vinyl-sourcemaps-apply/node_modules/source-map/lib/source-map/source-map-generator.js:232:34)
    at applySourceMap (/gui/client/node_modules/gulp-autoprefixer/node_modules/vinyl-sourcemaps-apply/index.js:23:15)
...

Interestingly, the path for that file should have a leading "..", e.g. "../components/deploy/deployer.scss" So I'm wondering if the paths are getting mangled within autoprefixer somehow?

polarathene commented 9 years ago

@JonRimmer Can you confirm that your node_modules are the same versions or greater than those mentioned in my initial post? If your node-sass is using an earlier version your libsass is outputting bad sourcemaps, you can verify this by compiling sass without autoprefixer and using the visualizer tool. If all your mappings are for a single line(bottom section) then your mappings are broken, autoprefixer doesn't have the correct information to work with.

Also have you tried writing the maps with these different approaches if your mappings are not showing any errors or issues visually with the tool?

.pipe(sourcemaps.write())
.pipe(sourcemaps.write({includeContent:false, sourceRoot:'../../scss/'})) // inline sourcemap without embedded sources
.pipe(sourcemaps.write('.', {includeContent:false, sourceRoot:'../../scss/'})) // external sourcemap without embedded sources, remove options to embed.

Just to clarify what those last 2 do. Inline sourcemap means it's included entirely in your css file without an external .map sourcemap file. Embedded sources means all your .scss/.less/.css code is included within the sourcemap(inline or external), when includeContent:true (default I think?) your sources are embedded. It's important to keep in mind that setting it to false, you need to tell the sourcemap how to find your source files, this is a relative file path from where the sourcemap is located(.css(inline) or .map(external) file location), in my example my scss folder is two folders up, if the sourceRoot is not correct then your external sources cannot be found, the soureRoot is more of a prefix, the rest of the filepath is listed in sources property, like your /components/deploy/deployer.scss/. If you do not set a sourceRoot by default it's likely /source/ which is used for embedded sources (includeContent:true). '.' at the start of write() allows you to write the sourcemap file externally.

If you have any success please let everyone know :) I can't tell if the other guys were helped since they're only posting again if they're still having issues.

jonrimmer commented 9 years ago

@polarathene OK, after much messing around and false starts, I have tracked down what is happening.

The problem is that the source map produced by gulp-autoprefixer contains the intermediate "app.css" produced by gulp-sass as a source file, both in the "sources" array and the "sourceContents" array. Thus when the mappings are loading in Chrome, the lines are just mapped back into app.css, rather than the individual .scss files.

This problem only seems to occur when one of the source .scss files contains a star delimited comment /* like this */

I have produced a small repository that demonstrates the problem: https://github.com/JonRimmer/sourcemaps-bug

If you check it out and run the default gulp task, it will run gulp-sass and gulp-autoprefixer on two files, with-comments.scss and without-comment.scss. If you then look at the .css.map files produced in the build directory, you will see that the one for with-comments.css contains "with-comments.css" as a source, whereas the map for "without-comment.css" doesn't.

Removing the prefix() step from the pipeline makes both maps output correctly, so this definitely seems to be something caused by gulp-autoprefixer, or one of its dependencies.

polarathene commented 9 years ago

@JonRimmer Thanks for the example, I've run that through to verify on my end. Not sure if this is worth noting but comparing the .css output with/without autoprefixer the sourcemap comment is added one line down than the source even though the input/output content is the exact same. If you write the file to disk without autoprefixer, and then use another gulp task after to put the compiled css through autoprefixer, your issue does not happen. Figured maybe it was a gulp-sourcemap issue, but I'm not seeing anything similar with minify or concat. Seems to be autoprefixer this time :) As a workaround, you could minify prior to autoprefixer to strip the comments out and avoid this issue.

@sindresorhus Can you look into this?

I'd actually be interested to know if minifying your LESS(those with the LESS issues) also fixes the issue with LESS and autoprefixer with sourcemaps?

boogerlad commented 9 years ago

Does there even exist a LESS minifier?

polarathene commented 9 years ago

@boogerlad compile LESS to css and then use a minifier? So use a pipe to compile your LESS, another to minify(gulp-minify-css) and then after that pipe autoprefixer, write sourcemaps and save to disk.

boogerlad commented 9 years ago

Ah I see what you mean. Changing the order from less -> autoprefixer -> concat -> minify to less -> concat -> minify -> autoprefixer fixed it for me. Thank you very much!

What is strange is that changing the order has increased the size of the map... I would've expected it to go down. I've attached a diff of the map here:https://www.diffchecker.com/ej9ltr37 Why are there more mappings?

EDIT: Duh, by changing the order the final output is larger too since minify isn't last. Here's the diff of the css files: https://www.diffchecker.com/mzf14xyl it seems changing the order makes autoprefixer do some funky things.

jonrimmer commented 9 years ago

@polarathene I went further down the rabbit hole of how sourcemaps work last night, and I now believe this issue is being caused by gulp-sass (or rather libsass), sort of.

The gory details are as follows: It comes down to how the build pipeline merges a sourcemap from one task with that produced in a subsequent task, such that lines in the final output can be mapped to their original source file(s).

Consider the following build pipeline:

source.scss ---> sass() ------> intermediate.css ------> prefix() ---> output.css
                   |                                        |
                 Map S ---> vinyl-sourcemaps-apply() <--- Map P
                                       |
                                     Map O -------- write() ---------> output.css.map

Maps S and P are generated independently by their respective steps, and only represent a mapping between their direct input and output files. To generate Map O, from output.css back to source.scss, vinyl-sourcemaps-apply (which delegates to Mozilla's sourcemaps lib) must merge the two maps.

To do the merge, the task loops through each mapping in Map P, and looks for an equivalent mapping for that line and run of text in Map S. If it finds one, then it knows where in source.scss the line in output.scss originated. If it can't find a mapping in Map S, then it assumes the line originated in intermediate.css. If intermediate.css isn't already present as a source in Map O, then it adds it, and includes a mapping from output.css to intermediate.css for that line.

In the case of the example I provided, the problem is that libsass does not generate mappings for star delimited comments, but Autoprefixer does (or maybe PostCSS does, there's a lot of delegation going on in all this). So when vinyl-sourcemaps-apply finds the mapping for the comment in Map P, it can't find any corresponding mapping in Map S, despite that line having been present in source.scss, and assumes it was introduced by libsass into intermediate.css. So it adds the intermediate.css file (called app.css in my example repo) as a source.

So the solution in this case is for libsass to include correct mappings for star delimited comments and everything else in its output. Unfortunately the situation WRT to sourcemap generation in libsass is still not great, despite recent improvements. I also found a bug with @charset that my app was triggering: sass/libsass#879. It results in every mapping in Map S being off by one line, which completely messes up the merge process and results in a useless Map O.

Avcajaraville commented 9 years ago

In addition to what was already said here, I also found out that it doest fail for this type of comments:

/*
 * COMMENT
 */

But it will fail with special characters, like umlaut.

I found out this while trying to compile angular-toaster css, which on the credits include one of the authors name "Fjällemark", resulting on the error discussed here.

Changing this name into "Fjaellemark", solves the issue.

So maybe its depends on the characters used.

Hope this info is useful for somebody.

Cheers !

nicky-lenaers commented 9 years ago

So, any fixes yet for using gulp-sass + gulp-autoprefixer + gulp-sourcemaps? As far as I could read, uncommenting the autoprefixer pipe seems to be the best solution so far.

Can't get it to work with ANY of the above solution (spend hours). Happy to hear solutions!

polarathene commented 9 years ago

@NickyL Did you follow my guide above for gulp-sass? Check that your using the right versions, nothing out of date. Libsass recently got a new update to help with mappings but I'm not sure when node-sass will update to use it. Avoid special characters and avoid a certain comment style and you shouldn't have a problem. If you still are try to provide small example that shows it.

What you could do is just compile your scss files without autoprefixer, then run a 2nd task on your compiled css file with autoprefixer, if you don't get a single good mapping from that, there is a multi-stage source map lib you can grab that merges sourcemaps into one.

rexmac commented 9 years ago

I can second what @JonRimmer experienced regarding star-delimited comments when using SASS (I know this ticket is for LESS). If my sass/scss files contain these kinds of comments anywhere in the file, then the final mapping includes the generated file in the "sources" array. If I remove gulp-autoprefixer from the build or if I change the comments to use double-slash notation, then everything works as expected. I haven't done any in-depth research on the issue, so I can't comment on whether this is an issue with gulp-autoprefixer or libsass, but as Jon seems to have done his homework, I'm inclined to believe the issue is with libsass. Unfortunately, their sourcemap support is rather....chaotic at the moment (as the maintainers freely admit; see https://github.com/sass/libsass/issues/621 and https://github.com/sass/libsass/pull/792).

neagle commented 9 years ago

Adding a minification step before autoprefixer solved this issue for me perfectly: big thanks to @JonRimmer and @polarathene. My fixed pipeline (in case it helps others) looks like this:

gulp.task('sass', ['sass-includes'], function () {
    return gulp.src('./src/scss/app.scss')
    .pipe(sourcemaps.init())
    .pipe(sass({
        includePaths: bourbon.includePaths,
        errLogToConsole: true
    }))
    // This is a LOAD-BEARING minification!
    .pipe(minifyCSS())
    .pipe(autoprefix()
            .on('error', notify.onError({
                title: 'Autoprefix Error',
                message: '<%= error.message %>'
            }))
        )
    .pipe(sourcemaps.write('./maps'))
    .pipe(gulp.dest('./assets/css'));
});
blob42 commented 9 years ago

Thanx @neagle :+1:

dsebastien commented 9 years ago

Thanks @neagle, that did the trick for me as well.

YNWA commented 9 years ago

Unfortunately, the @neagle's trick doesn't work for me with Less instead of Sass

JetFault commented 9 years ago

@YNWA is right. Doesn't work for me with Less

traverse commented 9 years ago

Even though this is for gulp-less it's still not working for me with gulp-sass either, it's still linking to the css file instead of the scss.

Versions:

"devDependencies": {
    "gulp": "^3.9.0",
    "gulp-autoprefixer": "^2.3.1",
    "gulp-sass": "^2.0.3",
    "gulp-sourcemaps": "^1.5.2"
}

Gulpfile:

var gulp         = require('gulp');
var sass         = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps   = require('gulp-sourcemaps');

gulp.task('sass', function() {
  gulp.src('scss/*.scss')
    .pipe(sourcemaps.init())
    .pipe(sass())
    .pipe(autoprefixer())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('css'))
});

Disabling autoprefixer "fixes" it but I was wondering if there's maybe a different workaround than having to minify or if there's more info about that it's actually libsass causing the issue for sass in particular?

polarathene commented 9 years ago

@Traverse it's not libsass at fault. Bring the issue up with postcss, from memory it's something to do with being passed the source map in the stream(handled by gulp-sourcemaps). You can split autoprefixer into a separate task that runs after the first one saves the css + map, it'll handle that fine from memory.