Yannick Schall
Yannick Schall

Reputation: 34999

Gulp tasks chaining

I'm using gulp to compile some .less files and inject the changes in the browser with live-reload.

This is the task I originally created:

var gulp = require('gulp');
var less = require('gulp-less');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var livereload = require('gulp-livereload');
var path = require('path');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer-core');
var mqpacker = require('css-mqpacker');
var csswring = require('csswring');

gulp.task('less', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    mqpacker,
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/'],
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
  .pipe(livereload());
});
gulp.task('watch', function() {
  gulp.watch('./**/*.less', ['less']);  // Watch all the .less files, then run the less task
});

gulp.task('default', ['watch']); // Default will run the 'entry' watch task

I created an other gulp task to perform the same tasks but using browser-sync instead of live-reload for cross testing:

var gulp = require('gulp');
var less = require('gulp-less');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var path = require('path');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer-core');
var csswring = require('csswring');
var browserSync = require('browser-sync').create();
var reload = browserSync.reload;

gulp.task('less', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/']
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
  .pipe(reload({stream: true}))
  // .pipe(livereload());
});
gulp.task('serve', ['less'], function() {

    browserSync.init({
        proxy: "http://my-site.dev/"
    });

    gulp.watch("./css/*.less", ['less']);
});

I then tried to compile both files to be able to run either task depending on if i'm doing local development or if testing. I've created a "less" task to compile the css, a "lrl" live reload watch task and a "bs" browser-sync watch task. I created the "less" task to remove the duplication but now when i change the css the browser reload everything instead of just injecting the css.

var gulp = require('gulp');
var less = require('gulp-less');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var path = require('path');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer-core');
var csswring = require('csswring');
var livereload = require('gulp-livereload');
var browserSync = require('browser-sync').create();
var reload = browserSync.reload;

gulp.task('less', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/']
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
});

gulp.task('lrl',['less'], function(){
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(livereload());
});


gulp.task('watch',['lrl'], function() {
  livereload.listen();
  gulp.watch('./**/*.less', ['lrl']);  // Watch all the .less files, then run the less task
});


// browser-sync setup
gulp.task('bs',['less'], function(){
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(reload({stream: true}))
});

gulp.task('serve', function() {
    browserSync.init({
        proxy: "http://my-site.dev/"
    });
    gulp.watch("./css/*.less", ['bs']);
    gulp.watch("./js/script.js").on('change', reload);
    gulp.watch("./templates/*.php").on('change', reload);
});

// run default task with live reload for local development
gulp.task('default', ['watch']); // Default will run the 'entry' watch task

I'm a bit confused with the way to call tasks within tasks. Is there a way to make sure that the css are injected, it's much faster to work on design this way.

Thanks a lot

=================== BIG EDIT ============================

I've been messing about with run-sequence but I still have the same problem. In some way the task is working. With the default task i get live-reload on my local server only. With gulp serve I get a server where i can debug my layout across browsers and devices. The problem is that i don't get css injection anymore. it looks like gulp keeps re-running all of the tasks and refresh the browser to reconnect it.

so I made a working version with duplicated code to make what i'm trying to achieve clearer

var gulp         = require('gulp'),
    less         = require('gulp-less'),
    watch        = require('gulp-watch'),
    plumber      = require('gulp-plumber'),
    path         = require('path'),
    postcss      = require('gulp-postcss'),
    autoprefixer = require('autoprefixer-core'),
    mqpacker     = require('css-mqpacker'),
    csswring     = require('csswring'),
    livereload   = require('gulp-livereload'),
    browserSync  = require('browser-sync').create(),
    reload       = browserSync.reload;


gulp.task('less-lrl', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    mqpacker,
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/'],
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
  .pipe(livereload());
});
gulp.task('watch', function() {
  livereload.listen();
  gulp.watch('./**/*.less', ['less-lrl']);  // Watch all the .less files, then run the less task
});


gulp.task('less-bs', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    mqpacker,
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/']
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
  .pipe(reload({stream: true}))
});
gulp.task('serve', ['less-bs'], function() {

  browserSync.init({
    proxy: "http://myserver.dev"
  });

  gulp.watch("./css/*.less", ['less-bs']);
});

gulp.task('default', ['watch']); // Default will run the 'entry' watch task

When I do this it works smoothly. But I wanted to avoid the code duplication from the "less-lrl" and "less-bs" tasks. The only thing that differ is .pipe(livereload()); and .pipe(reload({stream: true}))

There's some stoopid going on in my brain, i don't haz understand :)

Upvotes: 1

Views: 3118

Answers (4)

Katya Pavlenko
Katya Pavlenko

Reputation: 3383

I've got same issue with stylus. You can try two dest, it may help

 gulp.src('./css/style.less')  // only compile the entry file
  .pipe(less({
    paths: ['./css/']
  } ))
  .pipe(gulp.dest('./css/'))
  .pipe(postcss(processors))
  .pipe(gulp.dest('./css/'))
  .pipe(livereload());
});

Upvotes: 0

Yannick Schall
Yannick Schall

Reputation: 34999

I tried both suggested answers above but to no avail. I can't manage to create a "less" subtask to be shared with the "live-relaod" and "browser-sync" tasks (It does re-run all tasks all the time and i loose the benefits of css injection).

The best I managed to do is to run them together like this:

var gulp         = require('gulp'),
    less         = require('gulp-less'),
    watch        = require('gulp-watch'),
    plumber      = require('gulp-plumber'),
    path         = require('path'),
    postcss      = require('gulp-postcss'),
    autoprefixer = require('autoprefixer-core'),
    csswring     = require('csswring'),
    livereload   = require('gulp-livereload'),
    browserSync  = require('browser-sync').create(),
    reload       = browserSync.reload;


gulp.task('less', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];

  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/']
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
  .pipe(livereload());
});


gulp.task('watch', function() {
  livereload.listen();
  gulp.watch('./**/*.less', ['less']);  // Watch all the .less files, then run the less task
});

gulp.task('serve', function() {
    browserSync.init({
      //files: "**/*.css", 
     files: ['**/*.js', '**/*.php','**/*.css'], // is this better than gulp watch?
      proxy: "http://leadgen.dev/node/1272"
    });
    //gulp.watch("./js/script.js").on('change', reload);
    //gulp.watch("./templates/*.php").on('change', reload);
});

// run default task with live reload for local development
gulp.task('default', ['less', 'watch', 'serve']); // Default will run the 'entry' watch task

So now I have both tasks running together. I would still prefer to be able to switch between one or the other though.

Upvotes: 0

Felipe Skinner
Felipe Skinner

Reputation: 16636

If I understood your question correctly, the runSequence would solve your problem. Take a look here: https://www.npmjs.com/package/run-sequence

You just need to add

var runSequence = require('run-sequence');

And create a task that runs your desired ones. For example:

gulp.task('build', function(callback) {
  return runSequence(
    'less',
    ['lrl'],
    callback
  );
});

then

gulp.task('watch',['build'], function() {
  livereload.listen();
  gulp.watch('./**/*.less', ['build']);  // Watch all the .less files, then run the less task
});

Upvotes: 2

vsync
vsync

Reputation: 130810

note - please do not use both less and postcss together, since postcss was invented to replace and enhance what less does. Google it..

Please make sure LESS files path is correct!

Try it like this:

var gulp         = require('gulp'),
    less         = require('gulp-less'),
    watch        = require('gulp-watch'),
    plumber      = require('gulp-plumber'),
    path         = require('path'),
    postcss      = require('gulp-postcss'),
    autoprefixer = require('autoprefixer-core'),
    csswring     = require('csswring'),
    livereload   = require('gulp-livereload'),
    browserSync  = require('browser-sync').create(),
    reload       = browserSync.reload;


gulp.task('less', function() {
  var processors = [
    autoprefixer({browsers: ["last 2 version", "> 1%", "ie 9", "ie 8", "ie 7", "ios 6"]}),
    csswring({
      preserveHacks: true,
      removeAllComments: true
    })
  ];

  gulp.src('./**/*.less')  // only compile the entry file
  .pipe(plumber())
  .pipe(less({
    paths: ['./css/']
  } ))
  .pipe(postcss(processors))
  .pipe(plumber.stop())
  .pipe(gulp.dest('./css/'))
  .pipe(livereload());
});


gulp.task('watch', function() {
  livereload.listen();
  gulp.watch('./**/*.less', ['less']);  // Watch all the .less files, then run the less task
});


// browser-sync setup
gulp.task('bs',['less'], function(){
  gulp.src('./css/style.less')  // only compile the entry file
  .pipe(reload({stream: true}))
});

gulp.task('serve', function() {
    browserSync.init({
        proxy: "http://my-site.dev/"
    });
    gulp.watch("./css/*.less", ['bs']);
    gulp.watch("./js/script.js").on('change', reload);
    gulp.watch("./templates/*.php").on('change', reload);
});

// run default task with live reload for local development
gulp.task('default', ['less', 'watch']); // Default will run the 'entry' watch task

Upvotes: 1

Related Questions