New to Gulp. My default task is using the pluginrun-sequence which tells task deleteBuild to run, then makeBuild.
Randomly, I am getting an ENOENT error which seems to be telling me that I'm either referencing files that don't exist for deletion or copy. My tasks are:
deleteBuild:
gulp.task('deleteBuild', function(done) {
var del = require('del');
del(['build/**/*'], done);
});
makeBuild:
gulp.task('makeBuild', function() {
var stream = gulp.src(['src/**/*'], { base: 'src/' })
.pipe(gulp.dest('build/');
});
Can someone inform me as to how to best address this issue? I'm hoping to seek a low-level understanding rather than to be shown a solution w/o an explanation. Thanks.
Aside: I tried the deleteBuild without a callback function as well, under the assumption that, as is, it would perform the deletion and only continue to the next task once it is complete, though this doesn't seem to be what is happening.
That's probably because the deleteBuild does not return a gulp stream and thus leave the pipe broken. I would propose the following:
gulp.task('deleteBuild', function() {
var del = require('del');
var vinylPaths = require('vinyl-paths');
return gulp.src(['build']) // no need for glob, just delete the build directory
.pipe(vinylPaths(del));
});
gulp.task('makeBuild', function() {
var stream = gulp.src(['src/**/*'], { base: 'src/' })
.pipe(gulp.dest('build/');
});
gulp.task('default', function(cb) {
var runSequence = require('run-sequence');
runSequence('deleteBuild', ['makeBuild'], cb);
});
These tasks will first delete the build directory before executing the makeBuild task.
You'll need to install one additional plugin:
npm install vinyl-paths
For a ready to use example, please take a look a the gulpfile of skeletonSPA. This works for me ;-)
Related
I'm trying use gulp to bundle and minify my files using gulp-bundle-assets. Running the tasks on their own is fine. My problem is using gulp.watch to watch for any changes in my config file and re-bundle my scripts.
The first time the watch executes everything works correctly. On successive occasions everything runs, but the exact same files are bundled - any changes in the config are ignored.
If I run my "bundle" task while the watch is running, "bundle" will use the current configuration. While successive watches will continue to use the configuration on the first execution.
My guess would be the data for the stream retrieved by gulp.src is cached. So how do I tell it to always get the latest version?
var gulp = require('gulp');
var bundle = require('gulp-bundle-assets');
var del = require('del');
var index = 0;
gulp.task('bundle', function () {
console.log('Bundling files ' + (index++));
return gulp.src('./bundle.config.js')
.pipe(bundle())
.pipe(gulp.dest('./bundles'));
});
gulp.task('watch', function () {
gulp.watch(['./scripts/**/*.{js,css}', './bundle.config.js'], ['clean', 'bundle']);
});
gulp.task('clean', function (cb) {
console.log('Cleaning files');
del(['./bundles/**/*'], cb);
});
An alternative I tried was to use watch(...).on, and calling gulp.run, but that didn't fix the problem, either. I also tried pasting the code from the bundle task in to the on callback, but still got the same result.
The culprit isn't gulp.src(), but bundle(). The gulp-bundle-assets plugin uses require() to load your bundle.config.js. Since Node.js caches return values from require() you always get the same config object after the file is loaded for the first time.
The solution is to invalidate the require cache in your bundle task:
var gulp = require('gulp');
var bundle = require('gulp-bundle-assets');
var del = require('del');
var index = 0;
gulp.task('bundle', ['clean'], function () { // run clean task before bundle task
// invalidate require cache for ./bundle.config.js
delete require.cache[require.resolve('./bundle.config.js')];
console.log('Bundling files ' + (index++));
return gulp.src('./bundle.config.js')
.pipe(bundle())
.pipe(gulp.dest('./bundles'));
});
gulp.task('watch', function () {
gulp.watch(['./scripts/**/*.{js,css}',
'./bundle.config.js'], ['bundle']); // only run bundle task
});
gulp.task('clean', function () {
console.log('Cleaning files');
return del(['./bundles/**/*']); // return promise object
});
Unrelated to your problem, but I also fixed your clean task. The way you had it set up didn't work.
I have a Gulp task that uses glob-stream to recursively loop through directories and files to perform a task, similar to below, but far more elaborate:
var gs = require('glob-stream');
var config = {
PATH: 'some/path/*.*'
}
function doSomething(filePath) {
var stream = gs.create(filePath);
// Do something
return gs.on('data', doSomething);
}
gulp.task('compile', function() {
var filePath = config.PATH;
return doSomething(filePath);
});
I can have the task achieve the results and compile what I need, but unfortunately Gulp believes the task has finished while it's still running, causing issues in my build process - How can I avoid this? I'm already using run-sequence but to no effect.
Why are you manually walking the directory tree with a recursive function? Why not just let glob-stream do the work for you? Then you only have to take care of the //Do something part:
var config = {
PATH: 'some/path/**' //glob pattern for all subfolder and files
};
function doSomething(filePath) {
//Do something
}
gulp.task('compile', function() {
var stream = gs.create(config.PATH);
stream.on('data', doSomething);
return stream;
});
gulp.task('secondTask', function() {
console.log('secondTask');
});
gulp.task('default', function() {
runSequence('compile', 'secondTask');
});
The some/path/** glob pattern creates a stream of all folders and files below some/path/, so you don't have to implement the recursive tree walk yourself.
Note that the compile task returns the stream. Otherwise gulp can't tell when the compile task has completed and starts running secondTask before compile has finished.
I'm using the gulp-changed-in-place package to only run certain Gulp tasks with the files that have changed (https://github.com/alexgorbatchev/gulp-changed-in-place). I'm having an issue where I only want to run my linting and code style tasks on changed files to speed up development time.
My current setup is as follows:
var gulp = require('gulp');
var changedInPlace = require('gulp-changed-in-place');
var eslint = require('gulp-eslint');
var jscs = require('gulp-jscs');
var config = {
paths: {
js: './app/**/*.js'
}
}
gulp.task('jscs', function() {
return gulp.src(config.paths.js)
.pipe(changedInPlace())
.pipe(jscs())
.pipe(jscs.reporter())
.pipe(jscs.reporter('fail'));
});
gulp.task('lint', ['jscs'], function() {
return gulp.src(config.paths.js)
.pipe(changedInPlace())
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
gulp.task('js', ['lint'], function() {
// do some stuff
});
gulp.task('watch', function() {
gulp.watch(config.paths.js, ['js']);
});
The issue is probably pretty obvious. The js task has a dependency on the lint task which itself has a dependency on the jscs task - so the jscs task runs first. It accesses changedInPlace() which causes the cache to get updated and therefore the changedInPlace() call from the lint task doesn't think anything has changed and doesn't check the files I expect.
Has anyone used this package with this issue and do you have any suggestions on what to do? Also open to other ways of accomplishing the task - only running the js task on changed files.
I have a gulp watch task over a glob, looking for changes and updating an output folder. It is successfully able to updated changed files, add new files but it fails to remove deleted files.
The callback looks like this:
var cb = function (event) {
console.log('Moving assets...');
return gulp.src('app/assets/**/*', {base: 'app'})
.pipe(changed('build/assets'))
.pipe(gulp.dest('build'));
};
The gulp watch task is this:
gulp.watch('app/assets/**/*', cb);
I know that the gulp watch is running fine because the callback receives all the deleted events. But the callback itself is unable to remove the deleted file from the build/assets/ folder.
Do I have to explicitly handle the deleted event or am I missing something out?
The question is old, but I think it's still relevant.
Here is the solution I came up with, based on ondaplana answer in this github issue and the documentation of the gulp modules that are used:
Basically, it uses gulp-watch instead of gulp native watch function, to pipe gulp-filter and del modules.
var filter = require('gulp-filter');
var vinylPaths = require('vinyl-paths');
var del = require('del');
var watch = require('gulp-watch');
var notDeletedFilter = filter(
function(file) {
return file.event !== 'unlink' && file.event !== 'unlinkDir';
},
{restore: true}
);
notDeletedFilter.restore
.pipe(gulp.dest('dist'))
.pipe(vinylPaths(del));
//use gulp-watch instead of gulp native watch function
watch(['app/assets/**/*'], {events: ['add', 'change', 'unlink', 'unlinkDir']})
.pipe(notDeletedFilter)
.pipe(anyModule())
.pipe(gulp.dest('build'));
Documentation :
Gulp recipes
right now I have to stop and start this gulp script to clean and rebuild my dist file and then restart the server.
My watch file is clearly wrong, what do I change for it to restart the whole gulp script when a file is edited?
var gulp = require('gulp');
var connect = require('gulp-connect');
var concat = require('gulp-concat');
var clean = require('gulp-clean');
gulp.task('clean', function() {
return gulp.src('app/scripts/dist.js').pipe(clean());
});
gulp.task('scripts', ['clean'], function(){
gulp.src(['app/scripts/app.js', 'app/scripts/**/*.js', 'app/scripts/**/*/*.js'])
.pipe(concat('app/scripts/dist.js'))
.pipe(gulp.dest('.'));
});
gulp.task('webserver', function() {
connect.server();
});
gulp.task('watch', ['scripts'], function(){
gulp.watch('app/scripts' + '*.js', ['scripts']).on('change', function(evt) {
changeEvent(evt);
});
});
gulp.task('default', ['clean','scripts','webserver']);
Your glob for your watch seems to be wrong. Try this:
gulp.watch(['app/scripts/**/*.js', '!app/scripts/dist.js'], ['scripts']).on('change', function(evt) {
changeEvent(evt);
});
Use the exclude pattern for your dist.js to avoid an infinite loop.
Ciao
Ralf
In addition to my comment above:
Instead of setting your default task as the 3 tasks you have listed, do it like this.
gulp.task('watch',function(){
var scripts=gulp.watch(//scripts array,['scripts']);
scripts.on('change,function(evt){
changedEvt(evt) // remember to make sure this exists.
});
gulp.task('default',['watch']);
/* make sure to include watches for all the logic you want to get
executed within your watch tasks (similar to how I did it)
#== That way, you can still call those tasks from a different shell prompt
if you want, but they are set to always be executed when you
modify the related files.
*/