Gulp is one of the popular task runner tools which can be integrated and works well with various helper tools for code development. I've previously created a post about how Gulp can be interoperated with Nodemon. In this post, I try to show how it can work along with PM2. PM2 is a powerful process manager that can run on multiple platforms and support a variety of technologies.
PM2 is quite different from Nodemon. Nodemon specifically only focuses on monitoring of Node.js application. On the other hand, PM2 is a process manager with rich features for maintaining many application processes in a time, even with support for clustering mechanism. Besides, PM2 is usually implemented as a daemon program, so we will need a different approach to integrate it with Gulp.
For instance, we use Gulp to do some stuff such as linting, translating, or file copying after each code changes. After Gulp runs its main tasks, we will instruct Gulp to restart or stop the application process which is managed by PM2. Firstly, we set up the gulpfile.js
file. We just need an additional gulp-run
module for accessing PM2 API.
const gulp = require('gulp');
const { series, watch } = gulp;
const run = require('gulp-run');
function builtCleanerTask() { /* cleaning task */ }
function linterTask() { /* linting task */ }
function typescriptTask() { /* transpiling task */ }
function restartPM2Task() {
return run('pm2 restart ecosystem.config.js --env development').exec();
}
function stopPM2Task() {
return run('pm2 stop ecosystem.config.js').exec();
}
let watchingTasksList = [linterTask, typescriptTask, restartPM2Task];
let buildTasksList = [builtCleanerTask, linterTask, typescriptTask];
exports.build = series(buildTasksList);
exports.stop = stopPM2Task;
exports.watch = (done) => {
watch(['./src/**/*.ts'], {ignoreInitial:false, delay:1000}, series(watchingTasksList));
}
On the code above, we set a "watch" task to watch changes in Typescript files then perform actions for linting and translating. After that, we call a command to restart the process in PM2. The restart
command is safe to be run even we haven't initiated our application process in PM2 before. We also add a "stop" task to stop the process when we finish our code development.
In the package.json
file, we add some scripts to run the Gulp tasks as follows.
{
"script": {
"build": "gulp build",
"watch": "gulp build && gulp watch",
"stop": "gulp stop"
}
}
We can start the watch job by calling the npm run watch
command. To monitor our application log which is run by PM2, we need to open a new terminal and run the pm2 log
command. This is something different as usual when we need to use a different terminal to monitor our application because Gulp and PM2 are run separately. We need to call the npm run stop
command manually to stop the application process.
If we want to stop the application process in PM2 when we stop the watch job by pressing the Control + C
keys, we need to do a trick here. Gulp may have implemented an event listener to handle program termination. But, we need to intercept the Gulp process and stop the application process in PM2. We can utilize my approach as follows.
const { exec } = require('child_process');
// capture exit event
process.once('SIGINT', function() {
console.log("caught interrupt signal");
const pid = process.pid;
exec('pm2 stop ecosystem.config.cjs', (err,stdout,stderr) => {
setImmediate(() => {
process.kill(pid, 'SIGINT');
});
});
});
On the code above, we utilize the process.once()
method to only handle the first occurrence of the interrupt signal. We use a child process to stop the process in PM2. In the end, we don't call the process.exit()
method but call the process.kill()
method with the information of PID of the main process to let Gulp handle the rest of the termination process.
Comments
Post a Comment