Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Automatically reload your node.js app on file change with Gulp (https://github.com/wearefractal/gulp).
// NOTE: I previously suggested doing this through Grunt, but had plenty of problems with
// my set up. Grunt did some weird things with scope, and I ended up using nodemon. This
// setup is now using Gulp. It works exactly how I expect it to and is WAY more concise.
var gulp = require('gulp'),
spawn = require('child_process').spawn,
node;
/**
* $ gulp server
* description: launch the server. If there's a server already running, kill it.
*/
gulp.task('server', function() {
if (node) node.kill()
node = spawn('node', ['index.js'], {stdio: 'inherit'})
node.on('close', function (code) {
if (code === 8) {
gulp.log('Error detected, waiting for changes...');
}
});
})
/**
* $ gulp
* description: start the development environment
*/
gulp.task('default', function() {
gulp.run('server')
gulp.watch(['./index.js', './lib/**/*.js'], function() {
gulp.run('server')
})
// Need to watch for sass changes too? Just add another watch call!
// no more messing around with grunt-concurrent or the like. Gulp is
// async by default.
})
// clean up if an error goes unhandled.
process.on('exit', function() {
if (node) node.kill()
})
@Gerst20051

This comment has been minimized.

Copy link

@Gerst20051 Gerst20051 commented Jun 17, 2015

👍 worked great!

@jhartman86

This comment has been minimized.

Copy link

@jhartman86 jhartman86 commented Aug 6, 2015

Nice work - nodemon seemed to be causing a lot of unneccessary overhead. So... thanks!

@grebett

This comment has been minimized.

Copy link

@grebett grebett commented Aug 13, 2015

I've used my own version based on your idea. Simple, but very efficient. Thanks for sharing!

@inspective

This comment has been minimized.

Copy link

@inspective inspective commented Sep 3, 2015

Great !. It work for me.

@machadogj

This comment has been minimized.

Copy link

@machadogj machadogj commented Sep 4, 2015

Nice and simple! You might want to throw gulp-util to the mix, gulp.log will throw an error.

@RodrigoBastos

This comment has been minimized.

Copy link

@RodrigoBastos RodrigoBastos commented Nov 26, 2015

Great work! 👍

@khalilovcmd

This comment has been minimized.

Copy link

@khalilovcmd khalilovcmd commented Dec 19, 2015

Perfect!

@josephjaniga

This comment has been minimized.

Copy link

@josephjaniga josephjaniga commented Jan 7, 2016

Awesome, was in the process of writing this myself but you beat me to the punch. cheers 🍻

@roobottom

This comment has been minimized.

Copy link

@roobottom roobottom commented Jan 17, 2016

Brilliant! Thanks for this, saved me countless hours.

@connect-dips

This comment has been minimized.

Copy link

@connect-dips connect-dips commented Feb 16, 2016

Works just perfect! Awesome!

@Squeezo

This comment has been minimized.

Copy link

@Squeezo Squeezo commented Feb 23, 2016

Thanks for sharing!

@robmclarty

This comment has been minimized.

Copy link

@robmclarty robmclarty commented Jun 8, 2016

great little piece of nodesauce. <3

@TejasCMehta

This comment has been minimized.

Copy link

@TejasCMehta TejasCMehta commented Jun 10, 2016

Awesome!! 👍

@sylvery

This comment has been minimized.

Copy link

@sylvery sylvery commented Jul 6, 2016

Thanks a million! Saved me a lot of research :) 👍

@mircolac

This comment has been minimized.

Copy link

@mircolac mircolac commented Jul 7, 2016

Thanks a lot for this code. Works great!
Unfortunately gulp.run() is going to be deprecated and i was wondering if you're going to update this.
Meanwhile, i'll try to do it myself but i'm new with gulp so ... i'll try to do my best.
Thanks again anyway!

@anchal20

This comment has been minimized.

Copy link

@anchal20 anchal20 commented Aug 12, 2016

hi,
I am new to gulp and I am using gulp watch to watch the js changes. This was working fine sometime back but now gulp watch isnt watching anymore and every time I have to restart my server and run gulp command again. Please help me out!

Here is my sample gulp watch code :

**gulp.task('watch-babel', function() {
  gulp.watch('app/assets/javascripts/**/*.js', ['compile-babel']);
});**
@fyears

This comment has been minimized.

Copy link

@fyears fyears commented Aug 16, 2016

Great code!

But one improvement: The latest gulp does not have run(). We could use something like it to achieve the same goal:

gulp.task('default', ['server'], function() {
  gulp.watch(['./index.js', './lib/**/*.js'], ['server']);
})

(Also cc to @mircolac: My solution is the answer to your question).

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Nov 18, 2016

Thanks!

@alpertuna

This comment has been minimized.

Copy link

@alpertuna alpertuna commented Dec 12, 2016

Nice! Also thanks @machadogj for gulp-util to log.

@ncodes

This comment has been minimized.

Copy link

@ncodes ncodes commented Dec 30, 2016

Awesome! Thanks

@behrank

This comment has been minimized.

Copy link

@behrank behrank commented Jan 31, 2017

nice work!

@crowmagnumb

This comment has been minimized.

Copy link

@crowmagnumb crowmagnumb commented Feb 10, 2017

Yes, thank you! I just made server() a function so that you don't have to rely on gulp.run or any alternative...

const gulp = require('gulp');
const spawn = require('child_process').spawn;
let node;

function server() {
    if (node) {
        node.kill();
    }

    node = spawn('node', ['src/index.js'], {stdio: 'inherit'});
    node.on('close', function (code) {
        if (code === 8) {
            gulp.log('Error detected, waiting for changes...');
        }
    });
}

gulp.task('server', function() {
    server();
});

gulp.task('watch', ['server'], function() {
    gulp.watch(['./src/**/*.js'], function() {
        server();
    });
});

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

// clean up if an error goes unhandled.
process.on('exit', function() {
    if (node) {
        node.kill();
    }
});
@myuseringithub

This comment has been minimized.

Copy link

@myuseringithub myuseringithub commented Mar 1, 2017

For using BrowserSync (Browser reload) with server reload.

import childProcess from 'child_process'
var browserSync = require('browser-sync').create();
let node;
const INTERVAL = 10000;
const usePolling = true;

function serverLivereload() {
    if(node) node.kill()

    node = childProcess.fork('app.entrypoint.js', { cwd: '/app', stdio:'inherit' })
    node.on('message', (m) => {
        console.log('Server ready & listening.', m);
        browserSync.reload()
    });
    node.on('close', (code) => {
        if(code === 8) {
            gulp.log('Error detected, waiting for changes.')
        }
    })
}

gulp.task('watch:livereload', ()=> {
    browserSync.init({
        proxy: {
            target: 'localhost'
        },
        logLevel: 'debug',
        logConnections: true,
        ui: {
            port: 9901,
            weinre: {
                port: 9902
            }
        },
        port: 9903,
        open: false // open browser false.
    });
    serverLivereload()

	gulp.watch(
		[ 
            '/app/**/*.js', 
            '/app/**/*.css', 
            '/app/**/*.html', 
            '!/app/**/node_modules{,/**/*}' // equals to '!/app/{node_modules,node_modules/**/*}'
        ], 
	{ interval: INTERVAL, usePolling: usePolling },  // Fixed Windows issue, requiring legacy watch 'polling'
	async (done) => {
            serverLivereload()
            done()
        }        
	);
});

Then on forked child process: /app/app.entrypoint.js

import http from 'http'
import Koa from 'koa'
const serverKoa = module.exports = new Koa()
serverKoa.use(<middlewares>)
...
    http.createServer(serverKoa.callback()).listen(APP.port, ()=> {
        console.log(`listening on port ${APP.port}`)
        process.send({ message: 'Server ready & listening'});
    })

Run with gulp watch:livereload

@tiagosiebler

This comment has been minimized.

Copy link

@tiagosiebler tiagosiebler commented Oct 24, 2017

This makes everything SO much easier, awesome & thank you for sharing!

@tiagosiebler

This comment has been minimized.

Copy link

@tiagosiebler tiagosiebler commented Nov 16, 2017

By the way, if this launches too quickly and gets stuck. Instead of node.on('close') use node.on('sigterm') to handle the relaunch properly:

gulp.task('server', function() {
	runLiveServer();
	node.on('SIGTERM', function(code) {
		if (code === 8 || code === 12) {
			console.log('Error detected, attempting reboot...');
			setTimeout(runLiveServer, 500);
		} else {
			console.log('Relaunced with code: ', code);
		}
	});
})
@felixcatto

This comment has been minimized.

Copy link

@felixcatto felixcatto commented Feb 10, 2018

Awesome! Big thanks

@jorgevmendoza

This comment has been minimized.

Copy link

@jorgevmendoza jorgevmendoza commented May 24, 2018

Awesome! this saves tons of time!

@longtc

This comment has been minimized.

Copy link

@longtc longtc commented Jun 2, 2018

Never mind, I got it to work.
Make sure the task signal [Async Completion](https://github.com/gulpjs/gulp/blob/9f4a2e96506dec1d85804de8884678e72ffc5aa0/docs/getting-started/4-async-completion.md). Or, just define your task as an [`async` function](https://github.com/gulpjs/gulp/blob/9f4a2e96506dec1d85804de8884678e72ffc5aa0/docs/getting-started/4-async-completion.md#using-asyncawait):

```javascript
async function startServer() {
  if (node) node.kill();
  node = await spawn("node", ["./src/server.js"], { stdio: "inherit" });

  node.on("close", function (code) {
    if(code === 8) {
      console.log("Error detected, waiting for changes...");
    }
  });
}

gulp.task("default", function () {

  // Start the server, if a change is detected restart it
  gulp.watch(
    ["src/**/*", "src/server.js"],
    {
      queue: false,
      ignoreInitial: false // Execute task on startup 
    },
    startServer);
});
```
@b3none

This comment has been minimized.

Copy link

@b3none b3none commented Aug 4, 2018

👍

@lgcavalheiro

This comment has been minimized.

Copy link

@lgcavalheiro lgcavalheiro commented Sep 22, 2020

Hey man thanks for sharing your gulpfile, you got me out of one hell of a pickle haha!
Here's how mine endend up looking, works great now :D

const gulp = require('gulp');
const watch = gulp.watch;
const series = gulp.series;
const { exec, spawn } = require('child_process');
var serverProc = undefined;

const watcher = watch(['./frontend/**/*', './backend/**/*', '!./backend/**/*.json']);

watcher.on('change', function (path, stats) {
    console.log(`File ${path} was changed - Relaunching...`);
    serverProc.kill('SIGINT');
    exports.default();
});

watcher.on('error', function (e) {
    console.error(e.stack);
});

function purge() {
    return exec('shx rm -rf ./public/*');
}

function bundle() {
    return exec('parcel build ./frontend/html/*.html --out-dir public --no-source-maps');
}

function serve() {
    if (serverProc) serverProc.kill('SIGINT');
    serverProc = spawn('node', ['backend/server.js'], { stdio: 'inherit' });
    serverProc.on('close', function (code) {
        if (code === 8) {
            gulp.log('Error detected, waiting for changes...');
        }
    });
}

exports.default = series(purge, bundle, serve);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.