Sandwich Sandwich - 1 month ago 24
Sass (Sass) Question

Pass parameter to Gulp task in gulpfile.js (not command-line)

EDIT:
As I wrote IN THE TITLE AND FROM THE BEGINNING, this is not about command-line parameters and is thus NOT A DUPLICATE.
//EDIT


I have a Sass setup with an indefinite number of uniquely-designed pages (page_1, page_2, etc), each having their own
sass/pages/page_1/page_1.scss
file.

The pages all belong to the same website, and each page's sass file
@import
s the same set of files from a
sass/includes
folder.

With a basic gulp task watching
sass/**/*
, every page's styles get compiled anytime I make a change to any page's styles. Obviously this doesn't scale well.

I tried using
gulp-watch
, but it doesn't catch if changes are made to one of the included
.scss
files. It only catches changes made to the files that actually get compiled into an equivalent
.css
.

For the purposes of having my gulpfile be as DRY as possible, the best solution I could come up with was to maintain a basic array of folder names in
gulpfile.js
, and to loop through and watch each of them separately, using the same sass-compiling task for each folder.

var pageFolderNames = [
'page_1',
'page_2'
// etc
];


Then for the gulp task, I have:

gulp.task('watch_pages', function()
{
// Get array length
var numPages = pageFolderNames.length;

// Add a new watch task for each individual page
for (var i = 0; i < numPages; i++)
{
gulp.watch('sass/pages/' + pageFolderNames[i] + '/**/*.scss', ['sass_page']);
}
});


The (simplified) task that compiles sass:

// Task: Compile page-specific Sass
gulp.task('sass_page', function()
{
return gulp.src('sass/pages/' + pageFolderNames[i] +'/**/*.scss')
.pipe(plumber(plumberErrorHandler))
.pipe(sass(...))
.pipe(gulp.dest('css/pages/' + pageFolderNames[i]));
});


This approach (I know my JS-fu is weaksauce) results in an error:

'sass_page' errored after 71 μs
ReferenceError: i is not defined


Is there any way to pass parameters, such as
i
, to gulp tasks to get this working? Alternately, is there a better way to accomplish what I'm trying to do? I have a sneaking suspicion there is. :-/

Answer

I found out there is an on change event for gulp watch. So this might be what you're looking for:

var pagesDir = 'sass/pages/';

gulp.task('watch_pages', function() {
    gulp.watch(pagesDir + '**/*')
        .on("change", function(file) {
            // absolute path to folder that needs watching
            var changedDest = path.join(__dirname, pagesDir);
            // relative path to changed file
            var changedFile = path.relative(changedDest, file.path);
            // split the relative path, get the specific folder with changes
            var pageFolder  = changedFile.split('\\')[0];

            gulp.src(path.join(pagesDir, pageFolder) +'/**/*.scss')
              .pipe(plumber(plumberErrorHandler))
              .pipe(sass(...))
              .pipe(gulp.dest('css/pages/' + pageFolder));

            console.log(changedDest);
            console.log(changedFile);
            console.log(pageFolder);
        });
});

Also, this way you don't need to declare the folder variables. If you add directories within the path being watched, it should pick it up and name the destination folder accordingly.

Theoretically the gulp task to compile sass should work within the watch task. I played around with the paths, and it seems to spitting them out. Let me know what happens, I can modify if necessary.

The required packages:

var gulp = require("gulp"),
    path = require("path"),
    rimraf = require("rimraf");

BTW, since you already have access to the file path, you can perhaps target the specific scss file instead of the whole directory.

Comments