Gulp watch task does't exit on Ctrl C - javascript

Background
I am having this gulp watch task to handle sass compilation:
import gulp from 'gulp';
import sass from 'gulp-sass';
import concat from 'gulp-concat';
gulp.task("compile-scss", () => {
return gulp.src("assets/scss/**/*.scss")
.pipe(sass({ outputStyle: 'compressed' })
.on("error", sass.logError))
.pipe(concat("style.css"))
.pipe(gulp.dest("dist/css"));
});
gulp.task("watch-scss", ['compile-scss'], () => {
gulp.watch("assets/scss/**/*.scss", ["compile-scss"]);
});
I am then running gulp watch-scss and the process correctly compiles my files and start watching for new changes.
The problem
When I want watching to stop I am pressing Ctrl+C in the terminal and everything looks ok.
But then I make a change in the .scss file and expect it not be handled by the gulp task (should be already stopped). Anyway this change gets handled by the watch task as it seems still running.
Looking at the terminal code you can see where I start gulp watch-scss, where I press Ctrl+C and where task continues executing on change.
Environment details
OS: OS X 10.11 (El Capitan)
gulp version: 3.9.1
node version: 6.2.2
babel-core version: 6.11.4
History
The problem could be related to Node itself. Going into that direction I tried several solutions like terminating the process from within gulp like so:
process.on('SIGINT', function() {
process.exit();
});
It didn't help.
Read lot of info on that topic, but nothing helped. Here are two related questions, which didn't help either:
Stop a gulp watch task?
Terminate gulp-watch task
I can provide more details if needed.

Close the terminal and the session will be terminated. Run gulp again and try if CTRL + C works.

Related

Running parcel bundler from command line doesn't stop the process

I have a simple JS file that runs parcel bundler:
const Bundler = require('parcel-bundler');
(async () => {
const bundler = new Bundler('./src/index.html', {}); // options omitted for simplicity
await bundler.bundle();
})();
I run it from CLI with:
node ./build.js
While bundler works fine and creates bundled files in the dist folder, the process never exits, but rather remains in the async loop.
I tried adding then callback or using return but none of it helped.
Using process.exit() would of course stop the process but would also limit me from chaining this command in the CI, which is the whole purpose.
What am I doing wrong?
You need to set watch: false in your options to let Parcel know it should not watch but just build it once.
The default option is watch: true, so whenever you change something in your files, Parcel will recognize the change and rebuild your application.

Set environment mode and output messages when starting a gulp task

I'm wondering how I can output messages to the terminal when I run a gulp process and how I can set an environment to run tasks in specific ways.
I'm sure I've seen something like gulp scripts:dev before but don't know how to use, can anyone advice how I can do this?
How would you run the default task this way, gulp deafult:dev?
Is it possible to ask the user which environment they want to run the task for in the terminal when the execute the gulp command, if they don't specify it.
I've used the gulp-if plugin to achieve this but it works slightly differently, you need to set a node environment variable before running gulp i.e. NODE_ENV=dev gulp.
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
gulpif = require('gulp-if'),
shell = require('gulp-shell');
var isDev = process.env.NODE_ENV === 'dev';
// gulp-shell task to output messages to terminal
gulp.task('info', shell.task([
'echo run in developer mode with this command: NODE_ENV=dev gulp'
]));
// Styles Task
// Uses gulp-if plugin to run task differently dependent on env.
gulp.task('styles', ['info'], function () { // eslint-disable-line strict
return sass('css/sass/*.scss', {
style: gulpif(!isDev,'compressed','expanded'),
cacheLocation: 'css/sass/.sass-cache',
sourcemap: isDev
})
[...code ommitted...]
});
gulp.task('default', ['h','styles']);
Also I've used gulp-shell above to output messages to the terminal, but it's pretty basic. Is there anyway I can do something similar with line breaks and colours with the message I output to the terminal.
Take a look at gulp-environments - you can set as many as you like but dev and prod are sufficient for most. You can define each in the gulpfile and set different events to occur from within each gulp script. So your styles script can contain a .pipe(dev(some dev only sourcemap code))and a .pipe(prod(some mini fixed build code)). You can run the script from git bash with an --env flag... gulp --env dev or gulp --env prod. And run two completely different build cycles from more or less the same script. You set your default gulp task to run all your page scripts and it will only execute the ones for each environment as it loops.
To output messages to the terminal you can require gulp-util node module.
Example code:
gulp.task('test', () => {
gutil.log(gutil.colors.yellow('=== Testing ==='));
});

Gulp error in WebStorm: Failed to list gulp tasks

My WebStorm has stopped read and run gulp tasks.
It was working fine until last Friday.
This is an error that appears in console:
Failed to list gulp tasks in questionary/gulpfile.js: Failed to parse
JSON -> Unterminated array at line 1 column 5 path $[1] * Edit
settings
$ /usr/local/bin/node
/Users/rkon2006/Projects/My/questionary/node_modules/gulp/bin/gulp.js
--no-color --gulpfile /Users/rkon2006/Projects/My/questionary/gulpfile.js --tasks-json
[17:26:14] Using gulpfile ~/Projects/My/questionary/gulpfile.js
[17:26:14] Starting 'default'... Default task...
This is the code from my gulpfile.js (it doesn't start even with this code):
var gulp = require('gulp');
gulp.task('default', function () {
console.log('Default task...');
});
Process finished with exit code 0
I use gulp v4.0, node js 4.1.1 (tried defferent versions from 0.10.28 up to 4.1.1) and npm 2.14.4.
Do you have any ideas about this?
I have the same problem with webstorm after install a updated version of node.
The solution for me is the following:
In the block Gulp where webstorm show the list of task, click the cog icon and select gulp settings, in the section "Gulp package" add the path to the local gulp package(the gulp inside the node_modules in your project).
Example of path: yourproject\node_modules\gulp
Update node version and npm itself, that did the trick.
The problem is that some text is logged to standard output stream when evaluating gulpfile.js, but before running any gulp task (i.e. logging happens outside of gulp tasks);
possible workarounds:
Avoid logging anything to standard output stream outside of gulp
tasks.
Or
Don't log to standard output stream if it's started for listing
tasks, like:
if (!isListingTasks()) {
console.log('[my info]');
}
function isListingTasks() {
return process.argv[process.argv.length - 1] === '--tasks-json';
}
I was having same problem and it was fixed by selecting different Node Interpreter version e.g. in the below image I selected 8.9.2 and then clicked small refresh button in Gulp window and the issue was fixed.

Gulp 'Open' task doesn't correctly execute

Below are snippets from my gulpfile and basically the problem I'm experiencing is that open doesn't always open a new browser window whenever 'gulp' is executed from the CLI. For instance if I delete the generated 'dist' folder and execute 'gulp' then the 'dist' will scaffold out with the .html files and assets structure but it will fail to open the site in my browser window...
If I then cancel the gulp task that's currently running and execute it from the CLI again (with the 'dist' folder in place) then gulp will load the site in a new browser window as it should.
How do I set open up so that it executes every time no matter what? I'm thinking it's clashing with the 'clean' task somehow but I'm not quite sure.
Any help would be appreciated.
Clean task:
gulp.task('clean', function() {
gulp.src(['./dist/**/*.*'], { read: true })
.pipe(clean())
});
Open task:
gulp.task('open', function() {
gulp.src(config.startpage)
.pipe(open(config.startpage, { url: 'http://localhost:'+config.http_port }));
});
Default task:
gulp.task('default', ['html', 'scripts', 'styles', 'images', 'open', 'clean'], function() {
server.listen(config.livereload_port);
http.createServer(ecstatic({ root: 'dist/' } )).listen(config.http_port);
// gutil.log(gutil.colors.yellow('HTTP Server running on port:'), gutil.colors.red(config.http_port));
gulp.watch(config.src_sass, ['styles'])._watcher.on('all', livereload);
gulp.watch(config.src_js, ['scripts'])._watcher.on('all', livereload);
gulp.watch(config.src_html, ['html'])._watcher.on('all', livereload);
});
*Config.start_page points to dist/index.html
You have two related issues:
You need to return the streams within your tasks, or gulp won't know that they've completed. If you don't return a stream, return a promise, or use the callback function, gulp assumes the task is synchronous.
This is important, because it completely breaks task dependencies. gulp calls a task, sees that it's synchronous, and then immediately starts the next task.
Simply change your tasks to look like this :
gulp.task('clean', function() {
return gulp.src(['./dist/**/*.*'], { read: true })
.pipe(clean())
});
gulp currently has no way to run non-dependent tasks in a specified order. In your default task, those dependencies are all going to be run simultaneously, unless they depend on each other.
Since I doubt you want to force the clean task to run everytime you run the other tasks, the other solution is to use a 3rd party library to run tasks in sequence. (This is my library, written to solve this exact issue.) Eventually, hopefully, they will have a way to fix this natively.
Note: you still need to fix problem 1 for run-sequence to work.

Using node-inspector with Grunt tasks

Does someone used node-inspector with Grunt for application debugging? If not, Can you recommend a debugging tool for Grunt based apps?
I'm working with nodejs for a server side app and I have Grunt to use separated tasks (this is because users can execute tasks separately).
To run grunt in debug, you need to pass the grunt script to node explicitly:
node-debug $(which grunt) task
and put a debugger; line in your task. node-inspector will then open a browser with debugging tools.
Edit 28 Feb 2014
node-inspector has added the command node-debug, which launches node in a --debug state and opens the browser to the node-inspector page, stopping when it hits the first debugger line or set breakpoint.
Edit 30 January 2015
On Windows, things are a touch more complicated. See the answer from #e.gluhotorenko for instructions.
Windows solution
Run
node --debug-brk c:\Users\username\AppData\Roaming\npm\node_modules\grunt-cli\bin\grunt taskname
from cmd in the directory with your Gruntfile.js. Do not forget to put debugger; line in necessary places.
To debug, we have to modify the grunt file under bin. On my machine, grunt is installed globally, so I went to /usr/local/lib/node_modules/grunt/bin
I opened the file and modified:
#!/usr/bin/env node
To
#!/usr/bin/env node --debug-brk
--debug-brk will break on the first line of javascript ran.
Doing that alone isn't quite enough though, since you won't be able to find you're grunt task js file in the drop down in node inspector, so you have to modify the file you're interested in debugging by adding debugger; where you want the breakpoint to happen.
Now you can click continue after the first break, and you'll break on you're debugger; line
Pretty kludgy, but it's the only way I've found so far.
I recently created grunt-node-inspector to easily configure node-inspector with the rest of your grunt workflow, check it out: https://github.com/ChrisWren/grunt-node-inspector
Here is a section of a Gruntfile which illustrates how you can debug a grunt task using grunt-node-inspector, grunt-concurrent, and grunt-shell: https://github.com/CabinJS/Cabin/blob/master/Gruntfile.js#L44-L77
I have done a task to run my app and launch node-inspector.
It is far better than current proposition, you just have to add this task in gruntfile:
grunt.registerTask('debug', 'My debug task.', function() {
var done = this.async();
grunt.util.spawn({
cmd: 'node',
args: ['--debug', 'app.js'],
opts: {
//cwd: current workin directory
}
},
function (error, result, code) {
if (error) {
grunt.log.write (result);
grunt.fail.fatal(error);
}
done();
});
grunt.log.writeln ('node started');
grunt.util.spawn({
cmd: 'node-inspector',
args: ['&'],
opts: {
//cwd: current workin directory
}
},
function (error, result, code) {
if (error) {
grunt.log.write (result);
grunt.fail.fatal(error);
}
done();
});
grunt.log.writeln ('inspector started');
});
Great answers here. In 2017, now you can do
node --inspect --debug-brk $(which grunt) taskName
Which prints something like.
To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/232652c3-f63c-4b00-8de9-17dfad5db471
Open that URL in chrome, and you're good to go!
I'm using Node 7.3.0 and I'm on Mac. You might have to follow some of the advice in other posts to get it going on Windows.
2019 update
If you want to launch the grunt task in debug mode and break at first line:
node --inspect-brk $(which grunt) taskName
If you want to launch the grunt task in debug mode at a specific port:
node --inspect-brk=8080 $(which grunt) taskName
if you want to attache VSCODE to the node process running the debugging session of grunt, use the following configuration in vscode:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach by port IP 5656",
"port": 8080
}
]
}

Categories

Resources