Luke P. Issac Luke P. Issac - 22 days ago 13
Javascript Question

How to fix, ENOENT error: no such file or directory when the "fonts" task mentioned below in the gulpfile.js starts

Following is the gulpfile.js which i have. Am getting ENOENT error: no such file or directory, when the "fonts" task starts, while running "gulp build-qa" command. Howeve, The build is successful every alternate time but not every time consistently. How to fix this issue ? I have made sure that every task has return, even though it is not working.

var gulp = require('gulp'),
del = require('del'),
pump = require('pump'),
flatten = require('gulp-flatten'),
usemin = require('gulp-usemin'),
htmlmin = require('gulp-htmlmin'),
cssmin = require('gulp-clean-css'),
uglifyjs = require('gulp-uglify'),
stripdebug = require('gulp-strip-debug'),
ngannotate = require('gulp-ng-annotate'),
rev = require('gulp-rev'),
concat = require('gulp-concat'),
sourcemaps = require('gulp-sourcemaps'),
connect = require('gulp-connect');

var ENV = process.env.NODE_ENV || 'dev',
APP_DIR = 'app',
BUILD_DIR = 'build',
SRC_DIR = 'source',
ZIP_DIR = 'packed';


gulp.task('clean', function () {
return del(
[BUILD_DIR + '/**', ZIP_DIR + '/**'],
{ dryRun: false })
.then(
// paths => { console.log('Files and folders that would be deleted:\n', paths.join('\n'));}
);
});


gulp.task('build-qa',['clean','fonts','images','partials','usemin-qa'], function(){});



/* Html processing, minifying and copying to build folder */
gulp.task('partials', function () {
return gulp.src(['**/*.html','!index.html'], {cwd: APP_DIR})
.pipe(htmlmin({ collapseWhitespace: true }))
.pipe(gulp.dest(BUILD_DIR));
});

/* Images copying to build folder */
gulp.task('images', function () {
return gulp.src('**/*.{jpg,png,gif,svg}')
.pipe(flatten())
.pipe(gulp.dest(BUILD_DIR+'/images'));
});

/* Find all font type files in 'fonts' folders and move to fonts build folder with flattened structure */
gulp.task('fonts', function () {
return gulp.src('**/fonts/*.{ttf,woff,eot,svg}')
.pipe(flatten())
.pipe(gulp.dest(BUILD_DIR+'/fonts'));
});

gulp.task('usemin-qa', function () {
return gulp.src('app/index.html')
.pipe(usemin({
// pipelines are named in the HTML, like js_lib and js_app below; html is the src file
html: [htmlmin({ collapseWhitespace: true, quotes: true, empty: true, spare: true, loose: true })],
css_lib: [
cssmin(),
'concat',
rev()
],
css: [
cssmin(),
'concat',
rev()
],
js_lib: [
ngannotate({remove: false, add: true}),
uglifyjs(),
rev()
],
js_app: [
sourcemaps.init(),
'concat',
ngannotate({remove: true, add: true}),
uglifyjs(),
rev()
]
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(BUILD_DIR))
});

Answer

ENOENT errors in gulp are almost always caused by some kind of race condition.

The first problem is that all your tasks are sourcing files not just from your source folders. For example '**/fonts/*.{ttf,woff,eot,svg}' selects font files from anywhere in your project including your BUILD_DIR. You need to exclude BUILD_DIR in all your tasks:

gulp.task('fonts', function () {
    return gulp.src(['**/fonts/*.{ttf,woff,eot,svg}', 
                     '!'+BUILD_DIR+'/**'])
        .pipe(flatten())
        .pipe(gulp.dest(BUILD_DIR+'/fonts'));
});

The next problem is this line:

gulp.task('build-qa',['clean','fonts','images','partials','usemin-qa'], function(){});

This doesn't do what you think it does. All those tasks aren't executed in order, they're all executed at the same time. That means your clean task is deleting files in BUILD_DIR while your other tasks are busy copying files into that same directory.

You have two options:

(1) Place a dependency hint on all the other tasks. For example your fonts task would have to look like this:

gulp.task('fonts', ['clean'], function () {
    return gulp.src(['**/fonts/*.{ttf,woff,eot,svg}', 
                     '!' + BUILD_DIR + '/**'])
        .pipe(flatten())
        .pipe(gulp.dest(BUILD_DIR+'/fonts'));
});

This makes sure that all the other tasks run only after the clean task has finished.

(2) Use run-sequence in your build-qa task:

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

gulp.task('build-qa', function(cb) {
  runSequence('clean',['fonts','images','partials','usemin-qa'], cb);
});

This runs the clean task first and then all the other tasks in parallel.