Optimizing gulp watch task - javascript

I'm new to gulp and I've got a couple of gulp questions that I hope are pretty easy (meaning I'll probably have one of those forehead smacking moments when I hear the answer)...
My gulpfile has a number of repetitive one-way copy tasks, and then I'm watching these separate tasks in the watch command, however I'm almost certain that the way I'm doing it is totally inefficient.
Also, I'm noticing some interesting behavior, the copy command for syncHtmlRootDir task works exactly as I hoped (it will delete files as necessary), but none of my other one way copy tasks will remove deleted files, and I'm guessing it's a pathing issue, but I'm stumped on it.
gulpfile.js
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css')
var uglify = require('gulp-uglify');
var newer = require('gulp-newer');
var path = require('path');
var del = require('del');
function handleError (error) {
console.log(error.toString())
this.emit('end')
}
//setup browerSync to serve from both src and dist directories.
gulp.task('browserSync', function() {
browserSync.init({
server: {
baseDir: ["./", "src"] // ./ signifies root of folder, allows to load files from dist and src folders.
},
})
});
//one way sync of root folder
gulp.task('syncHtmlRootDir', function(done) {
return gulp.src(['src/*.html'])
.pipe(newer('dist/'))
.pipe(gulp.dest('dist/'))
.pipe(browserSync.reload({
stream: true
}))
});
//one way sync of app folder
gulp.task('syncHtmlAppDir', function(done) {
return gulp.src(['src/app/**/*'])
.pipe(newer('dist/app/'))
.pipe(gulp.dest('dist/app/'))
.pipe(browserSync.reload({
stream: true
}))
});
//one way sync of image folder
gulp.task('syncImgDir', function(done) {
return gulp.src(['src/assets/img/**/*'])
.pipe(newer('dist/assets/img/'))
.pipe(gulp.dest('dist/assets/img/'))
.pipe(browserSync.reload({
stream: true
}))
});
//copy and compile SCSS code
gulp.task('compileSass', function() {
return gulp.src('src/assets/css/**/*.scss')
.pipe(sass())
.on('error', handleError)
.pipe(minifyCss())
.pipe(gulp.dest('dist/assets/css'))
.pipe(browserSync.reload({
stream: true
}))
});
//minify JS
gulp.task('uglifyJS', function() {
gulp.src('src/assets/js/**/*.js')
.pipe(uglify())
.on('error', handleError)
.pipe(gulp.dest('dist/assets/js'))
.pipe(browserSync.reload({
stream: true
}))
});
//watch tasks
gulp.task('watch', ['browserSync'], function() {
var rootDir = gulp.watch('src/*.html', ['syncHtmlRootDir']);
rootDir.on('change', function(ev) {
if(ev.type === 'deleted') {
del(path.relative('./', ev.path).replace('src','dist'));
}
});
var appDir = gulp.watch('src/app/**/*', ['syncHtmlAppDir']);
appDir.on('change', function(ev) {
if(ev.type === 'deleted') {
del(path.relative('./', ev.path).replace('src/app/','dist/app/'));
}
});
var imgDir = gulp.watch('src/assets/img/**/*', ['syncImgDir']);
imgDir.on('change', function(ev) {
if(ev.type === 'deleted') {
del(path.relative('./', ev.path).replace('src/assets/img/','dist/assets/img/'));
}
});
var jsDir = gulp.watch('src/assets/js/**/*', ['uglifyJS']);
jsDir.on('change', function(ev) {
if(ev.type === 'deleted') {
del(path.relative('./', ev.path).replace('src/assets/js/','dist/assets/js/'));
}
});
var cssDir = gulp.watch('src/assets/css/**/*', ['compileSass']);
cssDir.on('change', function(ev) {
if(ev.type === 'deleted') {
del(path.relative('./', ev.path).replace('src/assets/css/','dist/assets/css/'));
}
});
});
So I'm 1) looking to combine my repetitive copy tasks into fewer tasks 2)have the delete file function work on all copy tasks and 3) optimize my watch task function to reduce repetition.
p.s., I've also noticed that if I add new files to the watch folders, it won't "recognize" them until I restart the watch command, so my method of syncing isn't exactly bulletproof. =/
Your thoughts are most appreciated.
Thanks!

Related

how to setup gulp file for live reload

I am trying to add a couple of gulp tasks. I have a basic HTML site that I want to watch changes for and reload with updated changes. I am trying to use livereload to listen and changed. however when it reloads i get an error that the Port is already in use which makes sense. But I cannot find a solution. First time to use Gulp so any tips on making what I have done better is welcome
var gulp = require('gulp');
var livereload = require('gulp-livereload');
var rev = require('gulp-rev');
var clean = require('gulp-rimraf');
var runSequence = require('run-sequence').use(gulp);
var connect = require('gulp-connect');
gulp.task('build', function () {
// by default, gulp would pick `assets/css` as the base,
// so we need to set it explicitly:
return gulp.src(['assets/css/*.css','assets/css/**/*.css', 'assets/js/*.js', 'assets/js/**/*.js', 'assets/js/**/**/*.js', 'assets/img/**/*.jpg', 'assets/img/**/*.png'], { base: 'assets' })
.pipe(gulp.dest('build/assets')) // copy original assets to build dir
.pipe(rev())
.pipe(gulp.dest('build/assets')) // write rev'd assets to build dir
.pipe(rev.manifest())
.pipe(gulp.dest('build/assets')); // write manifest to build dir
});
gulp.task('copy', function () {
gulp.src('index.html')
.pipe(gulp.dest('build'));
gulp.src('assets/fonts/*.*')
.pipe(gulp.dest('build/assets/fonts'));
gulp.src('assets/fonts/revicons/*.*')
.pipe(gulp.dest('build/assets/fonts/revicons'));
});
gulp.task('clean', [], function() {
return gulp.src("build/*", { read: false }).pipe(clean());
});
gulp.task('watch', function () {
livereload.listen(35729, function(err) {
if(err) return console.log(err);
})
gulp.watch(['index.html', 'assets/css/*.css','assets/css/**/*.css', 'assets/js/*.js', 'assets/js/**/*.js', 'assets/js/**/**/*.js', 'assets/img/**/*.jpg', 'assets/img/**/*.png'], [], function (e) {
livereload.changed(e.path, 35729)
});
});
gulp.task('connect', function() {
connect.server({
host: '0.0.0.0',
root: 'build',
port: 8000,
livereload: true
});
});
gulp.task('default', function() {
runSequence(
'dist',
['connect', 'watch']
);
});
gulp.task('dist', ['clean'], function () {
gulp.start('build');
gulp.start('copy');
});
You may want to check on your host if any process has been running on port - 35729. You can kill that process and try to rerun this application. Find and kill process
or
you can try with different port number than 35729 in your code.
Hope this would help.

Convert gulp watch in gulp#3.9.1 to gulp#4

We are switching from gulp#3.9.1 to gulp#4 and are having trouble switching over. When we run gulp watch, we are getting the following errors and trying to figure out how to resolve it.
What is the proper way to convert the gulp watch task to work with gulp#4?
Error message
AssertionError [ERR_ASSERTION]: Task never defined: minify-css
Command: gulp watch
This should run minify-js then minify-css in order
minify-js should run after clean-scripts has completed successfully
minify-css should run after clean-css has completed successfully
Current tasks.
var gulp = require('gulp'),
cssmin = require('gulp-clean-css'),
clean = require('gulp-clean'),
uglify = require('gulp-uglify');
var src = {
js: 'js/some-dir/**/*.js',
css: 'css/some-dir/**/*.css'
};
var dest = {
js: 'js/dest/some-dir/**/*.js',
css: 'css/dest/some-dir/**/*.css'
};
gulp.task('clean-css', function() {
return gulp.src(dest.css)
.pipe(clean({read:false, force: true});
});
gulp.task('minify-css', ['clean-css'], function() {
gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
});
gulp.task('clean-scripts', function() {
return gulp.src(dest.js)
.pipe(clean({read:false, force: true});
});
gulp.task('minify-js', ['clean-scripts'], function() {
gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
});
gulp.task('watch', ['minify-js', 'minify-css'], function() {
gulp.watch(src.js, ['minify-js']);
gulp.watch(src.css, ['minify-css']);
});
We tried doing this, but it resulted in the error message
gulp.task('watch', gulp.series('minify-js', 'minify-css', function() {
gulp.watch(src.js, ['minify-js']);
gulp.watch(src.css, ['minify-css']);
}));
gulp.task('minify-css', gulp.series('clean-css', function() {
return gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
}));
gulp.task('minify-js', gulp.series('clean-scripts', function() {
return gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
}));
gulp.task('watch', gulp.series('minify-js', 'minify-css', function() {
gulp.watch(src.js, gulp.series('minify-js'));
gulp.watch(src.css, gulp.series('minify-css'));
}));
As #Abdaylan suggested, I also advocate switching to functions. Nevertheless, so you can see where your code was wrong, I have fixed it here. Gulp 4 does not use this syntax:
gulp.task('someTask', ['task1', 'task2'], function () {}); // gulp 3
Gulp 4:
gulp.task('someTask', gulp.series('task1', 'task2', function () {})); // gulp 4 with string tasks
or gulp.parallel. So you can use your gulp.task syntax (rather than named functions) if you modify them to use the signatures that gulp 4 supports as I did in your modified code at the top of this answer.
Gulp 4 with named functions:
gulp.task(someTask, gulp.series(task1, task2, function () {})); // gulp 4 with named functions
So with named functions, the tasks are not referred to as strings.
See also task never defined for other potential problems when migrating from gulp3 to gulp4 with the same error message.
I would recommend converting your minify-js, minify-css, clean-scripts and clean-css tasks to functions:
var dest = {
js: 'js/dest/some-dir/**/*.js',
css: 'css/dest/some-dir/**/*.css'
};
function cleanCss() {
return gulp.src(dest.css)
.pipe(clean({read:false, force: true});
});
function minifyCss() {
return gulp.src(src.css)
.pipe(cssmin())
.pipe(gulp.dest(dest.css));
});
function cleanScripts() {
return gulp.src(dest.js)
.pipe(clean({read:false, force: true});
});
function minifyJs() {
return gulp.src(src.js)
.pipe(uglify())
.pipe(gulp.dest(dest.js));
});
var minifyJsAndClean = gulp.series(minifyJs, cleanScripts);
var minifyCssAndClean = gulp.series(minifyCss, cleanCss);
var watchers = function (done) {
gulp.watch(src.js, minifyJs);
gulp.watch(src.css, minifyCss);
done();
}
gulp.task('watch', gulp.series(minifyJsAndClean, minifyCssAndClean, watchers));
I just ran into this a couple days ago myself. What worked for me was to run each task in its own gulp.watch() with the gulp.series() on the watch task call instead of the watch task itself. For example:
gulp.task('watch', function() {
gulp.watch(src.js, gulp.series('minify-js'));
gulp.watch(src.css, gulp.series('minify-css'));
});

Gulp 4 - watch not watching changes

Today I migrated to Gulp 4, but I'm not able to get my watch function to work.
// Watch
gulp.task('watch', gulp.series('typescript', 'sass', 'browserSync', function(){
gulp.watch('./app/styles/**/*.scss', gulp.series('sass'));
gulp.watch('app/scripts/**/*.ts', gulp.series('typescript'));
gulp.watch('./app/*.html', browserSync.reload);
}));
typescript, sass, browserSync will run but watch does not react to file changes.
I just had the same problem. You don't actually have a reference to the initialized browserSync inside your watch gulp task. Instead of having your browserSync.init function in a separate browserSync gulp task, move it to inside your watch task, and it should work. Hope this helps!
Example:
gulp.task('watch', gulp.series(function (){
browserSync.init({
proxy:"http://localhost:8888",
injectChanges: true,
plugins: ["bs-html-injector?files[]=*.html"]
});
var html = gulp.watch('development/index.html');
html.on('change', function(path, stats) {
console.log('you changed the html');
browserSync.notify("Compiling, please wait!");
browserSync.reload("index.html");
})
var js = gulp.watch('development/**/*.js');
js.on('change', function(path, stats) {
console.log('you changed the js');
browserSync.notify("Compiling, please wait!");
browserSync.reload();
})
var css = gulp.watch('development/**/*.css');
css.on('change', function(path, stats) {
console.log('you changed the css');
browserSync.notify("Injecting CSS!");
browserSync.reload("*.css");
})
}));
Change gulp.watch('app/scripts/**/*.ts', gulp.series('typescript')); to a absolute gulp.watch('./app/scripts/**/*.ts', gulp.series('typescript'));
Also i normally stick this syntax, per task.
var watcher = gulp.watch('js/**/*.js', gulp.parallel('concat', 'uglify'));
watcher.on('change', function(path, stats) {
console.log('File ' + path + ' was changed');
});
I had some issues too, and i found this tutorial of gulp 4, this is my gulpfile to compile scss and watch the Scss files, concat and compile to a main.min.css with autoprefix.
var gulp = require('gulp'),
concat = require('gulp-concat'),
autoprefixer = require('gulp-autoprefixer'),
sass = require('gulp-sass');
//task para o sass
var paths = {
styles: {
src: 'scss/**/*.scss',
dest: 'css'
}
};
function styles() {
return gulp
.src(paths.styles.src, {
sourcemaps: true
})
.pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError))
.pipe(concat('main.min.css'))
.pipe(autoprefixer({
browser: ['last 2 version', '> 5%'],
cascade: false
}))
.pipe(gulp.dest(paths.styles.dest));
}
function watch() {
gulp.watch(paths.styles.src, styles);
}
var build = gulp.parallel(styles, watch);
gulp.task(build);
gulp.task('default', build);
I think that on the gulp v4 you need to use the gulp.parallel. I'm digging to learn more about the new version.

Gulp browserify order/sort files

I've got a Gulp task using browserify and watchify. As you can see I've got four files. modules.js uses the class from overlay-model.js.
But browserify doens't keep the order I'm passing. Instead of that browserify puts the files in alphabetical order so it first uses modules.js.
I'll tried looking for a solution gulp sort doens't seem to work and I can't find a browserify-ish solution.
Anyone knows something about this?
var gulp = require('gulp');
var gutil = require('gulp-util');
var c = gutil.colors;
var sort = require('gulp-sort');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var watchify = require('watchify');
var babel = require('babelify');
function compile(watch) {
var bundler = watchify(browserify([
'./assets/js/overlay-model.js',
'./assets/js/slider.js',
'./assets/js/words.js',
'./assets/js/modules.js'
], {
debug: true
})
.transform(babel.configure({
presets: ['es2015']
})));
function rebundle() {
bundler.bundle()
.on('error', function(err) { console.error(err); this.emit('end'); })
.pipe(source('build.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./public'));
}
if (watch) {
gutil.log(`${c.cyan('scripts')}: watching`);
bundler.on('update', function() {
gutil.log(`${c.cyan('scripts')}: processing`);
rebundle();
});
}
rebundle();
}
function watch() {
return compile(true);
};
gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });
gulp.task('scripts', ['watch']);
I think typically you'll have just one entry point (modules.js in your case) that'll use require(...) to load other modules in order you want.
// modules.js
require('./overlay-model');
require('./slider');
require('./modules');
Then use browserify like:
browserify('./assets/js/modules.js', ...);

gulp.watch doesn't catch a new files

I have the following gulpfile
var gulp = require('gulp');
var clean = require('gulp-clean');
var rename = require('gulp-rename');
var coffee = require('gulp-coffee');
var cache = require('gulp-cached');
var path = require('path');
var dist = './Test/public/';
var assets = './Test/assets/';
var paths = {
coffee: ['./**/*.coffee']
};
var coffeeTask = function () {
console.log('coffeeTask');
return gulp.src(paths.coffee, { cwd: assets + '**' })
.pipe(cache('coffee'))
.pipe(coffee({ bare: true }))
.pipe(rename({
extname: ".coffee.js"
}))
.pipe(gulp.dest(dist));
};
gulp.task('clean', function() {
return gulp.src(dist)
.pipe(clean());
});
gulp.task('coffee', ['clean'], coffeeTask);
gulp.task('coffee-watch', coffeeTask);
gulp.task('build', ['clean', 'coffee']);
gulp.task('watch', ['build'], function() {
var w = gulp.watch(paths.coffee, ['coffee-watch']);
w.on('change', function(evt) {
console.log(evt);
});
});
gulp.task('default', ['build']);
The key point of this configuration is use the same tasks for deploy and watch processes (read "build" and "watch" tasks).
The problem is that watch task doesn't catche any new coffee files. Edited or removed coffee files are processed well. According the following issue it should works. What the reason is?
Solved by using gulp-watch module:
watch(paths.coffee, function(evt) {
gulp.start('coffee-watch');
});
The question no is how to remove in dist folder deleted file in assets folder?

Categories