0
votes

A lot of questions about this have already been asked but unfortunately none of them resolve my problem...

At the office, we have a custom PHP Framework and some apps who run with it in a vagrant box. A rule was defined long time ago concerning SCSS files. They are in a "scss" folder and compiling in ../ (which is most of the time the css folder). We're using npm and gulp-sass to do that, with gulp-autoprefixer.

Example : foo/bar/css/scss/foo.scss --> foo/bar/css/foo.css

The problem is that in our framework, we don't have a common "dest" folder for all, so the watch is currently like that :

framework/**/scss/**/*.scss

we have multiple submodules in the framework, and multiple possible path for scss folder, for example :

  • fw/submodule/_www/css/foo/bar/scss/
  • fw/submodule/subsubmodule/_www/css/foo/bar/fooagain/scss/
  • fw/submodule/views/tpl/library/libraryname/default/css/foo/bar/scss/

etc...

so in order to compile in the right place, we use gulp-rename (folder var is the name of the FW) to compile in ancestor folder.

gulp.task('sass', () => {
    return gulp.src([folder+'**/scss/**/*.scss'])
        .pipe(plumber())
        .pipe(sass(sassOptions))
        .pipe(autoprefixer(autoprefixerOptions))
        .pipe(rename((filePath) => {
            filePath.dirname = filePath.dirname.replace("scss", "");
        })).pipe(gulp.dest(folder));
});

The problem is : when you save a scss file, it compiles ~200 file. this. is. so. long.

A full compiling require between 8 and 20sec.

In our pre-production server, we have a bash that run and compiles all siblings scss files when you save one. But i'm failing doing it with gulp.

My wish is : a scss file is changed, we compile him and his siblings. Not every single scss file. You think it is possible ?

Thank's a lot.

3

3 Answers

0
votes

you could create function within gulpfile that would give you specific task for each "group" of scss files. something like this

function compileStylesTask(taskName, srcFiles, distFolder, compiledFileName) {
    gulp.task(taskName, function () {
        var style = gulp.src(srcFiles)
            .pipe(sass().on('error', sass.logError))
            .pipe(rename({basename: compiledFileName}))
            .pipe(gulp.dest(distFolder))
        return merge(style);
    });
}

compileStylesTask('someCustomCssTask', [
    'src/css/some.scss',
    'src/css/some2.scss'
], 'someCompiledName', '/dist/css');

And in your watch task you could now add watch for each group separately like this

gulp.task('watch', function () {
    gulp.watch('/src/scss/some.scss', ['someCustomCssTask']);
});

This will trigger only this specific scss task to run.

0
votes

Translation into English via Google, if something kicks him))

It turned out that only the modified file was compiled!

The output is:

file.scss
 - file.css
 - file.min.css
 - file.min.css.map

It did not work either to beat Watcher, that he would immediately create the file after the "oneSassFileCompile" function was launched, the files were created only after the Watcher stop.

Exit the situation - launch the assistant task. But again did not find how to transfer parameters. I had to resort to an external variable, I hope it does not work out that many files changed immediately and this variable did not manage to skip all the files.

Sorry for my english. And for my script too, the first time I write to NodeJS and the first time I ran into Gulp!

If it turns out to throw a parameter directly into the subtask, or even better to force the files to be created immediately when the function is called in Watcher, I will be very glad to see the solution!

tags: gulp sass watch only one file change and compile css autoprefixer minify and map

gulpfile.js code:

/**
 * Variables
 */
var gulp        = require('gulp'),
    argv        = require('yargs').argv,
    sass        = require('gulp-sass'),
    rename      = require('gulp-rename'),
    //cssmin      = require('gulp-cssnano'), - a very long initialization, because of what is not convenient for a constant launch, but on the watcher will probably rise norms
    cleanCSS    = require('gulp-clean-css'),
    prefix      = require('gulp-autoprefixer'),
    plumber     = require('gulp-plumber'),
    notify      = require('gulp-notify'),
    sassLint    = require('gulp-sass-lint'),
    sourcemaps  = require('gulp-sourcemaps');

// Temporary solution until gulp 4
// https://github.com/gulpjs/gulp/issues/355
var runSequence = require('run-sequence');

/**
 * Settings
 */
var sassProjectPath = 'templates/**/*.scss';
var sassOptions     = {
    outputStyle: 'expanded'
};
var prefixerOptions = {
    browsers: ['last 5 versions'],
    cascade: true
};


/**
 * Secondary functions
 */
var displayError = function(error) {
    // Initial building up of the error
    var errorString = '[' + error.plugin.error.bold + ']';
    errorString += ' ' + error.message.replace("\n",''); // Removes new line at the end

    // If the error contains the filename or line number add it to the string
    if(error.fileName)
        errorString += ' in ' + error.fileName;

    if(error.lineNumber)
        errorString += ' on line ' + error.lineNumber.bold;

    // This will output an error like the following:
    // [gulp-sass] error message in file_name on line 1
    console.error(errorString);
};
var onError      = function(err) {
    notify.onError({
        title:    "Gulp",
        subtitle: "Failure!",
        message:  "Error: <%= error.message %>",
        sound:    "Basso"
    })(err);
    this.emit('end');
};


// BUILD SUB-TASKS
// ---------------


/**
 * Compiling a single single SASS file
 */
var oneSassFileCompile = function(filePath, destinationDir){
    var fullFileName, fileName, baseDir;

    // Checking the parameters
    if(!filePath) {
        console.log('param filePath miss');
        return false;
    }

    // Find file paths
    fullFileName    = filePath.replace(/\\/g,'/').replace(/.*\//, '');
    fileName        = fullFileName.replace('.'+ fullFileName.split('.').pop(), '');
    baseDir         = filePath.replace(fullFileName, '');

    // If you do not specify a folder to save, use the current
    destinationDir         = destinationDir || baseDir;

    // Compile
    return gulp.src(filePath)
        // Error Handler
        .pipe(plumber({errorHandler: onError}))
        // For generic style.css.map
        .pipe(sourcemaps.init())
        // The actual compilation
        .pipe(sass(sassOptions))
        // Adding Manufacturer Prefixes
        .pipe(prefix(prefixerOptions))
        // Call the file
        .pipe(rename(fileName +'.css'))
        // Save the compiled version
        .pipe(gulp.dest(destinationDir))

        // Compress CSS
        //.pipe(cssmin())
        .pipe(cleanCSS())
        // Rename the suffix
        .pipe(rename({suffix: '.min'}))
        // Save the .map
        .pipe(sourcemaps.write('./'))
        // Save the compressed file
        .pipe(gulp.dest(destinationDir));
};

/**
 * Task to start compiling a specific file
 * For PHPStorm File Watcher
 */
gulp.task('sass-file', function() {
    var filePath        = argv.filePath,
        destinationDir  = argv.destDir;

    // Checking the parameters
    if(!filePath) {
        console.log('argv --filePath miss');
        return false;
    }
    return oneSassFileCompile(filePath, destinationDir)
});


/**
 * Compiling all SASS project files
 * TODO - customize the paths and check
 */
gulp.task('sass-project', function() {
    return gulp.src(sassProjectPath)
        .pipe(plumber({errorHandler: onError}))
        .pipe(sourcemaps.init())
        .pipe(sass(sassOptions))
        .pipe(prefix(prefixerOptions))
        .pipe(rename(fileName +'.css'))
        .pipe(gulp.dest('./'))

        // Compress CSS
        //.pipe(cssmin())
        .pipe(cleanCSS())
        .pipe(rename({suffix: '.min'}))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./'));
});


/**
 * Task checks the SASS project files
 * TODO - customize the paths and check
 */
gulp.task('sass-lint', function() {
    gulp.src(sassProjectPath)
        .pipe(sassLint())
        .pipe(sassLint.format())
        .pipe(sassLint.failOnError());
});


/**
 * Watcher for all SASS project files
 */
// An auxiliary variable to transfer the file path from the watcher to the task
var sassWatchFilePath = '';
gulp.task('sass-watch', function() {
    gulp.watch(sassProjectPath, function(watchEvent){
        console.log('Watcher catch: '+ watchEvent.type +' :: '+ watchEvent.path);

        // Skip deleting
        if(watchEvent.type === 'deleted')
            return;

        // We set the variable with the path and start the helper
        sassWatchFilePath = watchEvent.path;
        gulp.start('sass-watch-helper');
    });
});
/*
 * Taks helper, if you immediately call "oneSassFileCompile" in sass-watch,
  * then the files are not created until the process ends. watcher = (
 */
gulp.task('sass-watch-helper', function() {
    var tmpPath = sassWatchFilePath;
    sassWatchFilePath = null;
    // Compilation
    return oneSassFileCompile(tmpPath);
});


// BUILD TASKS
// ------------


/**
 * Default task
 */
gulp.task('default', function(done) {
    runSequence('sass-project', 'sass-watch', done);
});

/**
 * Project Collector
 */
gulp.task('build', function(done) {
    runSequence('sass-project', done);
});
0
votes

you might need gulp-changed or gulp-cached to filter the file that has changed for you.

so in your case it would be

const cached = require('gulp-cached');
gulp.task('sass', () => {
return gulp.src([folder+'**/scss/**/*.scss'])
    .pipe(cached('cached files')) // this will exclude the file that haven't changed
    .pipe(plumber())
    .pipe(sass(sassOptions))
    .pipe(autoprefixer(autoprefixerOptions))
    .pipe(rename((filePath) => {
        filePath.dirname = filePath.dirname.replace("scss", "");
    })).pipe(gulp.dest(folder));
});