1

I want to use gulp file with Magento instead of native grunt that Magento provides as a default build system for compilation of less files.Due to very slow nature of grunt, I decided to make own custom gulp workflow.

Gulp has many features and it is super fast then grunt.So far I have installed gulp, gulp-less and gulp-autoprefixer node plugins for ease of use.

This is the initial code for gulpfile.js in the root of the Magento application.

var fs = require('fs'),
    gulp = require('gulp'),
    less = require('gulp-less'),
    autoprefixer = require('gulp-autoprefixer'),
    sourcemaps = require('gulp-sourcemaps'),
    watch = require('gulp-watch'),
    livereload = require('gulp-livereload');

    //browserSync = require('browser-sync').create();




var themeconfig = {
    area: 'frontend',
    name: 'Magento/newtheme',
    locale: 'en_US',
}


var pubdir = 'pub/static/frontend/' + themeconfig.name + '/' + themeconfig.locale + '/**/*.less';
var cssdir = 'pub/static/frontend/' + themeconfig.name + '/' + themeconfig.locale + '/' + 'css/';

var filestowatch = [
        cssdir + 'styles-l.less',
        cssdir + 'styles-m.less',
        cssdir + 'custom.less',
];


var assetstowatch = fs.realpathSync(pubdir);

Now as per the code, I first import all the plugins and then made a custom config object for theme name and locale in Magento.

What I want to do is to resolve all the symlinks inside pub directory for gull watch so that when any of the file changes, I can automate the process and compile less files. But as gulp not watches for symlinks, I decided to make it as a glob pattern and resolve these all files and tried to make array of those all resolved files so that afterwards I can simply put that array inside gulp.watch function like that.

But because pubdir variable is glob, node filesystem function realpathSync is not accepting it as an argument and throws the error about ** is not a directory.

How to accomplish this task for resolving all of the symlinks to array of actual paths? So that assetstowatch is an array of all the files that needed to be watched.

gulp.task('lesscss', async function(){


    gulp.src(filestowatch)
        .pipe(sourcemaps.init())
        .pipe(less())
        // .pipe(autoprefixer({
        //    cascade: false
        // }))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest(cssdir))
        .pipe(livereload());
        //.pipe(browserSync.stream());
});

gulp.task('watch',function() {
    livereload.listen();
    gulp.watch(assetstowatch,gulp.series('lesscss'));
})
0

Finally, I succeeded in getting the array of all the paths relative to the project root in windows with this code in nodejs.

I put this code after the declaration of variable filestowatch.

var files = glob.sync(pubdir,{realpath:true});
var assetstowatch = [];
files.forEach(function(file,index){
    resolve = require('path').resolve;
    var actualwinpath = path.relative(process.cwd(),resolve(file));
    assetstowatch.push(actualwinpath.replace(/\\/g,"/"));
})

What it does is first creates files array with the help of glob.sync where we use a realpath to true to generate an actual path of all symlinks.

Then we initialize an empty array for assetstowatch which will be our files that needs to be watched.

But because these paths are absolute, we use a forEach loop to iterate through all of the paths and with the help of resolve and path.relative, we get the relative paths relative to our project root.

And due to the use of ugly backslashes in windows os for paths, we replaced them with forward slashes and pushes each entry to assetstowatch array to generate the files to watch.

And that's it. We have generated custom gulp workflow which can be run from the project root after publishing symlinks to the pub folder. Any changes in symlink will now be watched with gulp and thus cause the lesscss task to run.

What we just need to do is

gulp watch

Anyone can use this whole gulpfile.js in project root for gulp less compilation.

var fs = require('fs'),
    glob = require('glob'),
    path = require('path'),
    gulp = require('gulp'),
    less = require('gulp-less'),
    autoprefixer = require('gulp-autoprefixer'),
    sourcemaps = require('gulp-sourcemaps'),
    watch = require('gulp-watch'),
    livereload = require('gulp-livereload'),
    Glob = glob.Glob;

var themeconfig = {
    area: 'frontend',
    name: 'Magento/newtheme',
    locale: 'en_US',
}


var pubdir = 'pub/static/frontend/' + themeconfig.name + '/' + themeconfig.locale + '/**/*.less';
var cssdir = 'pub/static/frontend/' + themeconfig.name + '/' + themeconfig.locale + '/' + 'css/';

var filestowatch = [
        cssdir + 'styles-l.less',
        cssdir + 'styles-m.less',
        cssdir + 'custom.less',
];

var files = glob.sync(pubdir,{realpath:true});
var assetstowatch = [];
files.forEach(function(file,index){
    resolve = require('path').resolve;
    var actualwinpath = path.relative(process.cwd(),resolve(file));
    assetstowatch.push(actualwinpath.replace(/\\/g,"/"));
})

gulp.task('lesscss', async function(){
    gulp.src(filestowatch)
        .pipe(sourcemaps.init())
        .pipe(less())
        // .pipe(autoprefixer({
        //    cascade: false
        // }))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest(cssdir))
        .pipe(livereload());
        //.pipe(browserSync.stream());
});

gulp.task('watch',function() {
    livereload.listen();
    gulp.watch(assetstowatch,gulp.series('lesscss'));
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.