ducin ducin - 2 months ago 21
Javascript Question

gulp tasks race condition

I've got an issue with gulp tasks (a)synchrony. Following is my gulp file. Basically, I want to clean the directory first and then copy/produce some files into a fresh directory. The problem is race condition. I need to execute

clean
and then execute all the rest (inside
build
task).

Currently the execution either completes as expected or fails with ENOENT directory doesn't exist because of the race condition.

var gulp = require('gulp');
var concat = require('gulp-concat');
var clean = require('gulp-clean');
var cleanCSS = require('gulp-clean-css');

var cfg = {
js: {
vendor: [
'./node_modules/angular/angular.min.js',
'./node_modules/angular-translate/dist/angular-translate.min.js',
'./node_modules/angular-bootstrap/ui-bootstrap.min.js',
'./node_modules/angular-bootstrap/ui-bootstrap-tpls.min.js'
],
app: './app/js/*'
},
css: {
vendor: [
'./node_modules/bootstrap/dist/css/bootstrap.css',
'./node_modules/font-awesome/css/font-awesome.css'
],
app: './app/css/*'
}
};

gulp.task('clean', function () {
return gulp.src('./dist', {read: false})
.pipe(clean());
});

gulp.task('vendor-js', function() {
return gulp.src(cfg.js.vendor)
.pipe(concat('vendor.js'))
.pipe(gulp.dest('./dist/'));
});

gulp.task('app-js', function() {
return gulp.src(cfg.js.app)
.pipe(concat('app.js'))
.pipe(gulp.dest('./dist/'));
});

gulp.task('vendor-css', function() {
return gulp.src(cfg.css.vendor)
.pipe(cleanCSS({compatibility: 'ie8'}))
.pipe(concat('vendor.css'))
.pipe(gulp.dest('./dist/'));
});

gulp.task('app-css', function() {
return gulp.src(cfg.css.app)
.pipe(cleanCSS({compatibility: 'ie8'}))
.pipe(concat('app.css'))
.pipe(gulp.dest('./dist/'));
});

gulp.task('fonts', function() {
gulp.src('./app/fonts/**/*')
.pipe(gulp.dest('./dist/fonts'));

gulp.src('./node_modules/font-awesome/fonts/**/*')
.pipe(gulp.dest('./dist/fonts'));
});

gulp.task('build', [
'clean',
'vendor-js',
'app-js',
'vendor-css',
'app-css',
'fonts'
]);

gulp.task('default', ['build']);

Answer

Actually, gulp support for serial (synchronous) tasks is a little crappy, need to do overcomes, as if it was a non-standard requirements for applications...

As the clean task was already doing a return, the job was:

  • to define a task dependency on clean for each single task that requires it
  • afterwards, remove clean from build

The final solution is:

var gulp = require('gulp');
var concat = require('gulp-concat');
var clean = require('gulp-clean');
var uglify = require('gulp-uglify');
var cleanCSS = require('gulp-clean-css');

var cfg = {
  js: {
    vendor: [
      './node_modules/angular/angular.min.js',
      './node_modules/angular-translate/dist/angular-translate.min.js',
      './node_modules/angular-bootstrap/ui-bootstrap.min.js',
      './node_modules/angular-bootstrap/ui-bootstrap-tpls.min.js'
    ],
    app: './app/js/*'
  },
  css: {
    vendor: [
      './node_modules/bootstrap/dist/css/bootstrap.css',
      './node_modules/font-awesome/css/font-awesome.css'
    ],
    app: './app/css/*'
  },
  fonts: [
    './app/fonts/**/*',
    './node_modules/font-awesome/fonts/**/*',
    './node_modules/bootstrap/fonts/**/*'
  ]
};

gulp.task('clean', function () {
  return gulp.src('./dist', {read: false})
    .pipe(clean());
});

gulp.task('vendor-js', ['clean'], function() {
  return gulp.src(cfg.js.vendor)
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest('./dist/'));});

gulp.task('app-js', ['clean'], function() {
  return gulp.src(cfg.js.app)
    .pipe(uglify('app.js'))
    .pipe(gulp.dest('./dist/'));
});

gulp.task('vendor-css', ['clean'], function() {
  return gulp.src(cfg.css.vendor)
    .pipe(cleanCSS({compatibility: 'ie8'}))
    .pipe(concat('vendor.css'))
    .pipe(gulp.dest('./dist/'));
});

gulp.task('app-css', ['clean'], function() {
  return gulp.src(cfg.css.app)
    .pipe(cleanCSS({compatibility: 'ie8'}))
    .pipe(concat('app.css'))
    .pipe(gulp.dest('./dist/'));
});

gulp.task('fonts', function() {
  gulp.src(cfg.fonts)
    .pipe(gulp.dest('./fonts'));
});

gulp.task('build', [
  'vendor-js',
  'app-js',
  'vendor-css',
  'app-css',
  'fonts'
]);

gulp.task('default', ['build']);
Comments