Closed andrewjmead closed 9 years ago
Can you please confirm that the version you are using is the v1?
Yes, I'm on 1.0.0
. I found the problematic line:
res = autoprefixer(fileOpts).process(file.contents.toString(), {
map: file.sourceMap ? {annotation: false} : false, // ***** causing the issue
from: file.relative,
to: file.relative
});
postcss/autoprefixer readme.md
- Autoprefixer supports inline source maps too.
It seems like everything should work, but it's removing the css source map comment entirely.
I just discovered an inline
option that postcss/autoprefixer-core has:
res = autoprefixer(fileOpts).process(file.contents.toString(), {
map: {inline: true}, // let users of gulp-autoprefixer set some options
from: file.relative,
to: file.relative
});
This adds support for inline maps. Is this configuration exposed to users of gulp-autoprefixer
?
As mentioned in the readme gulp-sourcemaps is the blessed way to do source maps in gulp. You shouldn't have to mess around with individual plugins source map settings.
Hmmm, I'll give that another shot. I tried to setup source maps with gulp-sourcemaps but was not able to successfully do so.
https://github.com/floridoo/gulp-sourcemaps does not support sass/scss at the moment. I opened an issue with them, but I still with the source maps configs were exposed via this plugin.
gulp-sass
seems to only support inline source maps. When I switch to gulp-ruby-sass
, everything started to work well.
For the record, here is the final working task:
gulp.task('css:dev', function () {
return gulp.src('public/css/core.scss')
.pipe(sass({sourcemap: true, sourcemapPath: '../scss'}))
.on('error', function (error) {
console.error(error);
this.emit('end');
})
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(autoprefix({
browsers: ['last 2 versions']
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest('public/build/css/'))
.pipe(livereload({auto: false}));
});
@andrewjmead yup https://github.com/dlmanning/gulp-sass/pull/51
After upgrading to gulp-autoprefixer v1.0.0:
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
gulp.task('styles', function () {
return gulp.src('src/styles/bootstrap.less')
.pipe($.sourcemaps.init())
.pipe($.less())
.pipe($.autoprefixer())
.pipe($.sourcemaps.write())
.pipe(gulp.dest('./build/css'));
});
$ gulp styles
[09:58:04] Using gulpfile .\gulpfile.js
[09:58:04] Starting 'styles'...
events.js:72
throw er; // Unhandled 'error' event
^
Error: SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, or the source map's "file" property. Both were omitted.
at SourceMapGenerator_applySourceMap [as applySourceMap] (.\node_modules\gulp-autoprefixer\node_modules\vinyl-sourcemaps-apply\node_modules\source-map\lib\source-map\source-map-generator.js:171:17)
at applySourceMap (.\node_modules\gulp-autoprefixer\node_modules\vinyl-sourcemaps-apply\index.js:11:15)
at DestroyableTransform._transform (.\node_modules\gulp-autoprefixer\index.js:35:5)
at DestroyableTransform.Transform._read (.\node_modules\gulp-autoprefixer\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:184:10)
at DestroyableTransform.Transform._write (.\node_modules\gulp-autoprefixer\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:172:12)
at doWrite (.\node_modules\gulp-autoprefixer\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:237:10)
at writeOrBuffer (.\node_modules\gulp-autoprefixer\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:227:5)
at DestroyableTransform.Writable.write (.\node_modules\gulp-autoprefixer\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:194:11)
at write (.\node_modules\gulp-less\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:605:24)
at flow (.\node_modules\gulp-less\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:614:7)
Any ideas on how to fix it?
I'm having the same problems as @andrewjmead. When I run my SCSS files through gulp-ruby-sass
and then through the autoprefixer, a map file is indeed being generated, but not being referenced in the compiled CSS file. It still has an inline sourcemap. My task is as follows:
return gulp.src('./css/src/*.scss')
.pipe(plumber())
.pipe(sass({
noCache: false,
sourcemap: true,
style: 'compact'
sourcemapPath: './src'
}))
.pipe(sourcemaps.init({
loadMaps: true
}))
.pipe(autoprefixer({
browsers: ["last 2 versions", "> 1%", "ie 8", "ie 7"],
cascade: false
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest('./css/'));
@antwan1986 Are you sure that sourcemapPath
is correct?
If I've read the sourcemapPath
documentation correctly:
A relative path from the output CSS directory to the Sass source directory as seen by your web server.
My folder structure is as follows:
/gulpfile.js
/css/build.css
/css/src/build.scss
My sourcemapPath in this instance would be correct, no? from /css
to /css/src/
?
@antwan1986 Your sourcemapPath would be correct then. Can you try copying the rest of my task and seeing if that helps? Our look identical (and mine works) except for a few plugin options.
I'm having the same problem as @antwan1986 - I would like to use the external sourcemap but autoprefixer keeps overwriting the /# sourceMappingURL=css.map / if I follow the docs for gulp-autoprefixer, gulp-ruby-sass and gulp-sourcemaps.
@andrewjmead I tried your set up, but that gave me inline sourcemaps.
This is the closest I've got to getting it right, but a second map called styles.css.map.map
is being generated.
This is my gulpfile:
// Load Plugins
var gulp = require('gulp');
var Combine = require('stream-combiner');
var plugins = require('gulp-load-plugins')({ camelize: true });
var lr = require('tiny-lr');
var server = lr();
var sourcemaps = require('gulp-sourcemaps');
var sass = require('gulp-ruby-sass');
// Styles Task
gulp.task('styles', function() {
return gulp.src('library/scss/source/*.scss')
.pipe(sass({style: 'compact', compass: true}))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(plugins.autoprefixer('last 2 versions', 'ie 9', 'ios 6', 'android 4'))
.pipe(sourcemaps.write('../scss/source/', {addComment: true}))
.pipe(plugins.livereload(server))
.pipe(gulp.dest('library/css'))
.pipe(plugins.notify({ message: 'The styles tasks are done!' }));
});
// more tasks here
gulp.task('default', ['styles', 'plugins', 'scripts', 'watch']);
And this is what node has to say when I run gulp styles
Using gulpfile ~/path-to-my-file/gulpfile.js
[00:53:22] Starting 'styles'...
[00:53:22] gulp-ruby-sass: directory
[00:53:33] gulp-ruby-sass: write style.css
write style.css.map
[00:53:34] style.css.map was reloaded.
[00:53:34] style.css was reloaded.
[00:53:34] style.css.map.map was reloaded.
[00:53:34] style.css.map was reloaded.
[00:53:34] Live reload server listening on: 35729
[00:53:34] gulp-notify: [Gulp notification] The styles tasks are done!
[00:53:35] gulp-notify: [Gulp notification] The styles tasks are done!
[00:53:35] gulp-notify: [Gulp notification] The styles tasks are done!
[00:53:35] gulp-notify: [Gulp notification] The styles tasks are done!
[00:53:35] Finished 'styles' after 14 s
I've tried moving .pipe(sourcemaps.init({loadMaps: true}))
to after autoprefixer and I've also tried putting .pipe(sourcemaps.init())
there instead - none of these options work.
@MandyMadeThis I was unable to find a working combination aside from the one I posted :frowning:
Just retried your suggestions myself @andrewjmead, the sourcemap stays inline for me :(
Yeah, you might have to use inline maps (I have to). Are they not working or is there some other reason why you need external source maps?
I need them to be external for my production environments. I find them useful to have on production servers for easier debugging, however, the source map size can be considerable and there's no point in putting that extra weight onto the client / customer if they'll never use it themselves.
As mentioned in the readme gulp-sourcemaps is the blessed way to do source maps in gulp. You shouldn't have to mess around with individual plugins source map settings.
@sindresorhus I agree. The issue is that the two main SASS gulp tasks, gulp-sass
, and gulp-ruby-sass
have their own sourcemap settings. There is not good way to get all the plugins to work together.
@antwan1986 Here is a good solution for external sourcemaps.
Gulp-sass
only generates inline sourcemaps, but you can load those in with gulp-sourcemaps
, then save them as external sourcemaps with no extra files or strange things. Most of the problems I had came form open issues with gulp-ruby-sass
.
gulp.task('sass:main', function () {
return gulp.src('theme/scss/styles.scss')
.pipe(sass({sourceComments: 'map'}))
.on('error', function (error) {
console.error(error);
this.emit('end');
})
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(autoprefix({
browsers: ['last 2 versions']
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./theme/css'));
});
@andrewjmead - will this solution strip the inline sourcemap from the CSS file after the task runs? Or will you have both an external .map file and an inline soucemap?
@MandyMadeThis I should have clarified :smile:. This solution starts with an inline sourcemap (all gulp-sass
supports). Then the sourcemaps are loaded in and saved as external sourcemaps. The internal sourcemap is removed, and is replaced by a reference to the external sourcemap.
In the end, you have a css file with a path reference to an external sourcemap :smile:!
@andrewjmead I am trying your solution but once autoprefix()
is run, the sourcemap gets removed from the gulp-sass buffer and sourcemaps.write() doesn't load anything.
Resulting in a gulp-sourcemap-write: source file not found:<file path>
. However if I remove autoprefix, it generates the correct sourcemap but then I'm lacking any of the prefixed css.
gulp.task('sass', function () {
gulp.src(dir('static/sass/**/*.scss'))
.pipe(sass({
sourceComments: 'map',
includePaths: [dir('static/sass')]
}))
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(autoprefix({
browsers: ['last 2 versions']
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(dir('static/css')))
.pipe(reload({ stream: true }));
});
@jayzawrotny this is more complicated (as it includes prepending some vendor css) and working for me (pardon the coffee)
gulp = require('gulp')
autoprefixer = require('gulp-autoprefixer')
sass = require('gulp-sass')
reload = require('browser-sync').reload
sourcemaps = require('gulp-sourcemaps')
filter = require('gulp-filter')
merge = require('merge-stream')
concat = require('gulp-concat')
gulp.task('css', ->
vendor = gulp.src([
'node_modules/normalize.css/normalize.css'
])
main = gulp.src(['app/assets/css/main.sass'])
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(sourcemaps.write())
.pipe(sourcemaps.init(loadMaps: true))
.pipe(autoprefixer())
.pipe(sourcemaps.write())
merge(vendor, main)
.pipe(sourcemaps.init(loadMaps: true))
.pipe(concat("main.css"))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('public/css'))
.pipe(filter('**/*.css'))
.pipe(reload(stream: true))
)
I am having the same issue as @jayzawrotny, this works fine:
var startSassTask = lazypipe()
.pipe(sourcemaps.init)
.pipe(sass)
//.pipe(prefix)
.pipe(sourcemaps.write);
and as soon as I uncomment the .pipe(prefix)
(which is using gulp-autoprefixer
) then I get the error message:
gulp-sourcemap-write: source file not found: [path trying to find a css file but pointing at my sass dir]
@aaronjensen I think your solution only works if your src is a single file, not a glob
@valdelama I did a quick write up of my solution (it's also posted above): http://www.devworkflows.com/posts/getting-scss-auto-prefixer-and-source-map-to-play-nice/
@andrewjmead Thanks, I tried your solution and it did create a .map file but it wasn't recognised in chrome dev tools, or at least I couldn't see the .scss source files. If I use my code from above (with autoprefixer commented out) then I have inline sourcemaps that are picked up by chrome automatically. Also from what I can tell from the documentation it is now recommended to not use the gulp-sass built in sourcemaps and instead use gulp-sourcemaps for all plugins.
@valdelama I'm with you. The issue is that the gulp plugin (in this case gulp-sass) needs to explicitly support gulp-sourcemaps
. If plugin developers do support gulp-sourcemaps, awesome, but it's not supported automatically.
If the .map
file is generated, but it's not showing, there is a chance that it's invalid or that you don't have the chrome dev tools properly setup.
@andrewjmead gulp-sass does support it now, that's why if you check my code above you will see that this works fine (using gulp-sourcemaps):
var startSassTask = lazypipe()
.pipe(sourcemaps.init)
.pipe(sass)
//.pipe(prefix)
.pipe(sourcemaps.write);
but as soon as I uncomment the line calling gulp-autoprefixer then I get the gulp-sourcemap-write: source file not found
error which is what lead me to believe this is a problem with gulp-autoprefixer and not gulp-sass
@valdelama that does not work. This does: https://github.com/sindresorhus/gulp-autoprefixer/issues/1#issuecomment-57258788
I believe the problem is w/ autoprefixer, they either dont' support gulp-sourcemaps
properly or something else, but what I have in the comment works as a workaround
@andrewjmead you may consider updating your post now that gulp-sass
properly supports gulp-sourcemaps
:
gulp.task('sass:custom', function () {
return gulp.src('theme/scss/styles.scss')
.pipe(sourcemaps.init())
// Convert sass into css
.pipe(sass())
// Catch any SCSS errors and prevent them from crashing gulp
.on('error', function (error) {
console.error(error);
this.emit('end');
})
.pipe(sourcemaps.write())
// Load existing internal sourcemap
.pipe(sourcemaps.init({loadMaps: true}))
// Autoprefix properties
.pipe(autoprefixer({
browsers: ['last 2 versions']
}))
// Write final .map file
.pipe(sourcemaps.write('./'))
// Save the CSS
.pipe(gulp.dest('./theme/css'));
});
@aaronjensen I will :smile:
@aaronjensen @andrewjmead I did try that method as well and I get a different kind of error, like this:
"/vendor/assets/stylesheets/prism.scss" is not in the SourceMap.
basically it errors on the first src file in the main .scss file (which is not an issue when I leave autoprefixer out of it)
Cool, maybe my method broke with the latest gulp-sass update. I'll check it out.
@valdelama you've got latest gulp-autoprefixer and gulp-sass? could you paste the entire task?
@aaronjensen Package versions:
"gulp-autoprefixer": "^1.0.1",
"gulp-sass": "^1.0",
"gulp-sourcemaps": "^1.2.2"
Pasting the complete tasks is kind of difficult because it's broken up into multiple small reusable parts via lazy pipes but here's the relevant code:
var startSassTask = lazypipe()
.pipe(sourcemaps.init)
.pipe(sass, {
errLogToConsole: true,
includePaths: [vendorAssets.styles, bowerAssets, wegoAssets.styles, gemAssets],
imagePath: '/images'
})
.pipe(sourcemaps.write)
.pipe(sourcemaps.init, {loadMaps: true})
.pipe(prefix)
.pipe(sourcemaps.write, './');
var sassDevTask = startSassTask
.pipe(gulp.dest, publicAssets)
.pipe(browserSync.reload, {stream:true});
gulp.task('publicCss', function() {
return gulp.src('./' + appAssets.styles + '/public_pages.scss',
'./' + appAssets.styles + '/public_pages_ie8.scss')
.pipe(sassDevTask());
});
It's part of a pretty large gulp file to replace the rails asset pipeline.
Am I right in thinking that the way this should work in an ideal world is like this (simplified demo):
gulp.src('./scss/*.scss')
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(autoprefixer())
.pipe(sourcemaps.write())
.pipe('./css');
?
@valdelama looks like it's the same as mine, more or less. The only difference is I'm only passing one file through, perhaps that makes a difference in this house of cards :/
I believe what you pasted is how it should work, but it sounds like the problem is not w/ gulp-autoprefixer
(according to #8).
I needed to use gulp-ruby-sass because my project is also using compass and gulp-sass does not support compass. So I came up with a solution and it's working beautifully. I've got a development styles task that gives me external sourcemaps and a production styles task that autoprefixes everything for me - I don't need both in development, so this solution works great for me.
Here is what it looks like:
var gulp = require('gulp');
var plugins = require('gulp-load-plugins')({ camelize: true });
var livereload = require('gulp-livereload');
// errors function
function errorLog (error) {
console.error.bind(error);
this.emit('end');
}
// Development Styles Task
gulp.task('devStyles', function() {
return gulp.src('library/scss/main.scss')
.pipe(plugins.rubySass({ style: 'compact', compass: true }))
.on('error',errorLog)
.pipe(gulp.dest('library/css'))
.pipe(livereload())
.pipe(plugins.notify({ message: 'The dev styles are done!' }));
})
// Production Styles Task
gulp.task('prodStyles', function() {
return gulp.src('library/scss/main.scss')
.pipe(plugins.rubySass({ style: 'compressed', compass: true }))
.on('error',errorLog)
.pipe(plugins.autoprefixer( '> 1%', 'last 2 versions', 'ie 9', 'ios 6', 'android 4'))
.pipe(gulp.dest('library/css'))
.pipe(plugins.notify({ message: 'The production styles are done' }));
});
// A bunch more tasks here
// Multiple Gulp Tasks
// run: gulp for default tasks
gulp.task('default', ['devStyles', 'vendor', 'scripts', 'watch']);
// run: 'gulp build' for production tasks
gulp.task('build', ['prodStyles', 'vendor', 'scripts']);
@aaronjensen I'm unable to get gulp-sass to work with gulp-sourcemaps. I'm getting bad map files and duplicate map files: http://cl.ly/image/312o373X432e
The core.css.map file also does not work.
@andrewjmead i'm not sure how the collabs feel about this becoming the sass/autoprefixer sourcemaps support thread, but maybe you could put your gulp task in here, it sounds like maybe you're writing to a file twice write('./')
rather than writing inline write()
@aaronjensen Sorry, I just copied your example :smile:. My old way still works, so I'm just going to keep using that.
@aaronjensen @andrewjmead Just FYI, based on this comment I got it kind of working. Working as in I have sourcemaps and they lead me to the right file via dev tools however line numbers are wrong (as the original commentor mentions) and I still get the source file not found
warning.
I also updated gulp-sass to 1.1.0 and gulp-sourcemaps to 1.2.4 which might have helped.
This is the code I'm using (with lazypipes):
var startSassTask = lazypipe()
.pipe(sourcemaps.init)
.pipe(sass, {
errLogToConsole: true,
includePaths: [vendorAssets.styles, bowerAssets.styles, wegoAssets.styles, gemAssets.styles],
imagePath: (isDev ? '/images' : '/assets')
})
.pipe(sourcemaps.write, {includeContent: false})
.pipe(sourcemaps.init, {loadMaps: true})
.pipe(prefix, {cascade: false})
.pipe(sourcemaps.write);
Pretty sure the issue is related to libsass outputting an incorrect sourcemap, autoprefixer runs fine when provided a proper sourcemap. Check that without autoprefixer that your sourcemap in devtools maps to the correct line in .scss, in my case it was either null or the last line of the file. It'll be fixed with libsass 3.2, more info here
@andrewjmead @aaronjensen @antwan1986 @valdelama There was an update to gulp-sass
today, it supports the v2 beta of node-sass
and in turn libsass 3.1-beta
. The fixed mappings and bugfixes should solve this issue.
I've provided code examples that worked for me for inline and external sourcemaps with embedded or external sources. You can see them here.
I though it was an issue with
gulp-sass
, but it turns out thatgulp-autoprefixer
was the culprit.Problematic Task
Issue
After the scss is compiled into css, it has inline source maps that look like the following
Once that file is run through autoprefixer, the source maps don't exist. I wasn't able to find any documenation