1

I've been trying to get gulp sass and gulp sourcemaps to do exactly what I want and I'm finding it hard. I want to take a sass entry file (src/sass/index.scss), generate an output file (dist/css/index.css) and a separate sourcemap for that index file (dist/css/index.css.map) which has a sourceRoot set to the project base (absolute path: /home/damon/projects/test) and the sourcemap entries to be relative to that path.

Here's what I tried:

attempt 1: straight example code from gulp-sass:

var sassEntry = 'src/sass/index.scss';
gulp.src(sassEntry)
 .pipe(sourcemaps.init())
 .pipe(sass().on('error', sass.logError))
 .pipe(sourcemaps.write())
 .pipe(gulp.dest('dist/css'));

Outcome: this inlines the sourcemap into the CSS file so I can't tell if it's right or not.

attempt 2: write it to separate file

gulp.src(sassEntry)
 .pipe(sourcemaps.init())
 .pipe(sass().on('error', sass.logError))
 .pipe(sourcemaps.write('.'))
 .pipe(gulp.dest('dist/css'));

Outcome: writes a separate sourcemap, but the sourceRoot says '/sources/' (WTF is that?!, it doesn't exist and I never configured it) and the paths are all relative to the sass entry file, not the project base, which is also going to be meaningless when my browser tries to locate the source files.

attempt 3: try to fix the sourceroot (also I found includeContent: false)

gulp.src(sassEntry)
 .pipe(sourcemaps.init())
 .pipe(sass().on('error', sass.logError))
 .pipe(sourcemaps.write('.',{includeContent: false, sourceRoot: __dirname}))
 .pipe(gulp.dest('dist/css'));

Outcome: the sourceroot is now my working folder which is nice, the content isn't included which is nice, but the files in the sourcemap are still relative to the sass entry file not to the sourceRoot, so my map is still useless

attempt 4: Set the gulp.src base

gulp.src(sassEntry, { base: __dirname })
 .pipe(sourcemaps.init())
 .pipe(sass().on('error', sass.logError))
 .pipe(sourcemaps.write('.',{includeContent: false, sourceRoot: __dirname}))
 .pipe(gulp.dest('dist/css'));

Outcome: Infuriatingly, setting the base on gulp.src fixes the sourcemap - sourceRoot is still correct and the source file paths are relative to the sourceRoot, BUT it now outputs to dist/css/src/sass/index.css which is wrong. WTF!

attempt 5: use absolute paths

gulp.src(sassEntry, { base: __dirname })
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('.',{includeContent: false, sourceRoot: __dirname}))
.pipe(gulp.dest(__dirname + '/dist/css'));

Outcome: no change, it still outputs to the same deep structure in dist.

If anyone can enlighten me on how to do this I would be forever grateful.

Louis
  • 146,715
  • 28
  • 274
  • 320
Damon Smith
  • 1,770
  • 18
  • 24

2 Answers2

2

While Sven's answer is perfectly good, I also found an answer to my own question by getting a deeper understanding of how gulp works (which I was trying to avoid), and apparently gulp stores each matched file with a path, so adding:

{ base: __dirname }

in the gulp.src makes it that each matched file has the full path from the base, which then causes them to output with the full relative path from wherever you set the base to. The solution I ended up with was to use gulp-flatten, which removes those relative paths from files in the pipeline, so my eventual function looked like this:

gulp.src(sassEntry, { base: __dirname })
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('.',{includeContent: false, sourceRoot: __dirname}))
.pipe(flatten())
.pipe(gulp.dest(__dirname + '/dist/css'));

easy once you understand more about what it's trying to do I guess.

Damon Smith
  • 1,770
  • 18
  • 24
1

Since your attempt 4 does everything you want except place the resulting files in the wrong location, the easiest fix would be to just change that location with gulp-rename after the sourcemaps have been generated:

gulp.src(sassEntry, { base: __dirname })
 .pipe(sourcemaps.init())
 .pipe(sass().on('error', sass.logError))
 .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: __dirname}))
 .pipe(rename({dirname:''}))
 .pipe(gulp.dest('dist/css'));
Sven Schoenung
  • 30,224
  • 8
  • 65
  • 70
  • thanks, yes actually after reading around I found a solution too, which was to use gulp-flatten. Apparently when gulp.src finds files with a glob it stores each one with a path, and adding the base option to it adds the full base path to it. gulp-flatten allows you to remove those paths in your pipeline, so where you have rename you can also do .pipe(flatten()) and that solves it. – Damon Smith May 26 '16 at 23:57