I have the following task that I'm trying to use for development. I have two other tasks than I need run before gulp-nodemon starts and restarts my server process.
It STARTS just fine, but upon discovering a change in my /src file tree, the two tasks are run, but the node process never restarts and I never see my .on('restart') message fire. It then just hangs after the two other tasks complete (I get Gulp "Finished..." messages for both of them). Am I missing something here?
import gulp from 'gulp'
import nodemon from 'gulp-nodemon'
gulp('watch', ['copy-assets', 'transpile'], () => {
return nodemon({
execMap: {
js: `node`
},
script: `build/index.js`,
watch: `src/**/*.js`,
ext: `js`,
tasks: ['copy-assets', 'transpile']
}).on(`restart`, () => {
console.log(`App restarted!`)
})
})
Related
I have a gulp watch task as following:
gulp.task("watch", () => {
const watch = {
'dev': [src_folder + '**/*.njk', src_js_folder + '**/*.js'],
'css': [src_sass_folder + '**/*.scss']
}
gulp.watch(watch.dev, gulp.series("dev")).on("change", browserSync.reload);
gulp.watch(watch.css, gulp.series("sass"));
});
gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
So when there's any changes on *.sass files the sass task will run, and when there's changes on *.js and/or *.njk files the task dev will run.
The problem I'm having is when there are changes on *.sass, *.js and/or *.njk at the same time, the sass task will run twice in this case.
How can I skip the gulp.watch(watch.css, gulp.series("sass")); when the gulp.watch(watch.dev, gulp.series("dev")).on("change", browserSync.reload); is already run.
Problem
The double execution of the sass task when running the watch task occurs because in the code you have shared you are effectively defining the sass task to run twice.
gulp.task("watch", () => {
const watch = {
'dev': [src_folder + '**/*.njk', src_js_folder + '**/*.js'],
'css': [src_sass_folder + '**/*.scss']
}
// 1st execution > The `dev` task is defined into the `gulp.series()` as part
// of the combined tasks to run for this watcher, and, as `dev` contains the
// `sass` task in it this will run it the first time.
gulp.watch(watch.dev, gulp.series("dev")).on("change", browserSync.reload);
// 2nd execution > This watcher have the `sass` task defined into the
// `gulp.series()` as part of the combined tasks to run, this will run
// the second time
gulp.watch(watch.css, gulp.series("sass"));
});
// The `dev` task contains the`sass` task into the `gulp.series()` as part
// of the combined tasks to run
gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
Therefore, every time you run gulp dev the sass task will be executed only once, and every time you run gulp watch the sass task will be executed twice.
Solution
To solve this problem you could perhaps reorder the executions in a slightly different way. Here are some ideas of what some possible solutions might look like.
- Possible Solution 1
const paths = {
njk: src_folder + '**/*.njk',
js: src_js_folder + '**/*.js',
sass: src_sass_folder + '**/*.scss'
}
gulp.task("watch", () => {
gulp.watch([
paths.njk,
paths.js,
paths.sass
],
gulp.series("dev")
).on("change", browserSync.reload);
});
gulp.task("dev", gulp.series("merge-json", "nunjucks", "sass", "js"));
In this example, we define the sass task as part of the combined tasks to run defined within the gulp.series for the dev task. This will allow us to run gulp dev and execute all those tasks only once. It will also allow us to run gulp watch and execute the tasks defined for the dev task only once each time the files defined in paths are updated.
- Possible Solution 2
const paths = {
njk: src_folder + '**/*.njk',
js: src_js_folder + '**/*.js',
sass: src_sass_folder + '**/*.scss'
}
gulp.task("watch", () => {
gulp.watch([
paths.njk,
paths.js,
],
gulp.series("dev")
).on("change", browserSync.reload);
gulp.watch(paths.sass, gulp.series("sass");
});
gulp.task("dev", gulp.series("merge-json", "nunjucks", "js"));
gulp.task("another_extra_task", gulp.series("dev", "sass"));
In this example, we removed the sass task from the combined tasks to run for the dev task, also, we defined the another_extra_task task where we are combining the dev and sass tasks. This will allow us to run gulp another_extra_task and execute all the combined tasks defined for dev and the sass task, but also, it will allow us to run gulp watch without repeating the execution of the sass task since in the first watcher we execute the dev task where the sass task isn't defined anymore and we just execute it with the second watcher.
Conclusion
Since the definition of the tasks depends on each particular use case, I recommend you try to reorder the execution of them in a more granular way. See the following reference which explains how to avoid duplicating tasks https://gulpjs.com/docs/en/api/series#avoid-duplicating-tasks
I hope these possible solutions help you to understand the problem you are having in the code you have shared!
Assuming this is due to rapid file changes, it may help to set the watch delay option:
gulp.watch(watch.dev, { delay: 500 }, gulp.series("dev"))
If that does not help, you may need to figure out a way to de-bounce the events. There's an old package called gulp-debounce which seems to achieve that, but is unmaintained and so is likely incompatible, but viewing its source may grant some insights.
I am using Gulp 4 to compile my code from TypeScript to JavaScript and to build and serve the app.
I've come across one problem that I cannot solve.
I'd like to run the build, copy-html and copy-css tasks before some file gets changed.
According to Gulp documentation I just need to provide a config object with ignoreInitial set to false, but it doesn't work.
I've tried to call the three tasks before I initialize browserSync but for it also didn't work for me.
gulp.task("serve", function() {
// TODO Make a build before first serve
browserSync.init({
server: {
baseDir: "./dist/"
}
});
gulp
.watch(["src/**/*.ts", "src/**/*.html", "src/**/*.css"], {
ignoreInitial: false
})
.on(
"change",
gulp.series(
gulp.parallel("copy-html", "copy-css"),
build,
browserSync.reload
)
);
});
Instead of using calling .on() on the returned chokidar interface, add your tasks to the watch command.
gulp
.watch(
["src/**/*.ts", "src/**/*.html", "src/**/*.css"],
{ ignoreInitial: false },
gulp.series(
gulp.parallel("copy-html", "copy-css"),
build,
browserSync.reload
)
)
);
I've got the following:
gulp.watch('src/**/*', ['compile']);
gulp.watch('src/**/*', (event) => {
if (event.type === 'deleted' {
gulp.src(event.path.replace('src/', 'compiled/')).pipe(clean());
} else {
// TODO: Only run 'compile' when file is not deleted.
}
});
Whenever a file is added or modified I would like to run the compile task which will take the new file and move it into the compiled directory.
Whenever a file is deleted I do not want to run the compile task as it will do nothing. Instead, I need to remove the file from the compiled directory.
The above code works, but continues to run the compile task (resulting in a no-op) when a file is deleted.
How can I conditionally run another task? It looks like both the run and start Gulp methods have been removed and/or deprecated.
You can include {read: false} in your task which should work
gulp.task('default', function () {
return gulp.src('app/tmp', {read: false})
.pipe(clean());
gulp.task('dev', function () {
watch(['public/**', '!public/index.html'], function () {
del.sync(['web/**', '!web/.gitkeep', '!web/index.html', '!web/js/**']);
del.sync(['cordova/www/**', '!cordova/www/.gitkeep', '!cordova/www/index.html', '!cordova/www/js/**']);
gulp.src(['public/**', '!public/index.html', '!public/js/**'])
.pipe(gulp.dest('web/'))
.pipe(gulp.dest('cordova/www/'));
});
});
I'm using gulp setting up my development workflow. What I want to do is whenever any change happen in the public/, I want to wipe out everything in another two directory: web/ and cordova/www/, and write everything from public/ to web/ and cordova/www/.
I don't know what I'm doing wrong here. The dev gulp task job keeps throwing the error: EISDIR, read!
I'm configuring my gulp.js gulpfile to watch my directory for file changes, and 1) reload my express server and 2) issue a livereload "change" event so that my browser (with the LiveReload chrome extension) will reload the page that I'm developing.
Here's my gulpfile:
var gulp = require('gulp')
, nodemon = require('gulp-nodemon')
, livereload = require('gulp-livereload');
gulp.task('startReloadServer', function() {
livereload.listen();
});
gulp.task('demon', function () {
nodemon({
script: 'server.js',
ext: 'js html',
env: {
'NODE_ENV': 'development'
}
})
.on('start', ['startReloadServer'])
.on('restart', function () {
console.log('restarted!');
livereload.changed();
});
});
gulp.task('default', ['demon']);
Yet when I make a change to one of my view (.html) files, my browser reloads the page before the node server process has had an opportunity to come back online:
How do I alter my gulpfile to have the livereload.changed() event be issued after nodemon is ready to receive requests?
I found similar question, then I write my solution.
Gulp to watch when node app.listen() is invoked or to port (livereload, nodejs and gulp)
nodemon({script: 'app.js',
nodeArgs: ['--harmony'],
stdout: false})
.on('readable', function(data) {
this.stdout.on('data', function(chunk) {
if (/koa server listening/.test(chunk)) {
console.log('livereload');
livereload.reload();
}
process.stdout.write(chunk);
});
this.stderr.pipe(process.stderr);
});
I also ran into this problem. This best I could come up with was to delay the call to livereload.changed() for one second.
nodemon.on('restart', function() {
setTimeout(livereload.changed, 1000);
});
docs: setTimeout