How to prevent grunt-nodemon from restarting all apps - node.js

I'm running node on Windows 10. I have three node apps and I want to be able to start them all up with one handy grunt command. Furthermore, I want node to automatically restart if I modify any of the apps.
I'm using a combination of grunt-nodemon and grunt-concurrent for this. The node processes all start up fine.
The problem is that if I modify the code related to any of them they all restart, which takes a long time. How can I make it so that nodemon only restarts the app whose code I actually modified?
var loadGruntTasks = require('load-grunt-tasks')
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concurrent: {
runAll: {
tasks: ['nodemon:app1', 'nodemon:app2', 'nodemon:app3'],
options: {
logConcurrentOutput: true
}
}
},
nodemon: {
app1: {
script: './app1/app.js'
},
app2: {
script: './app2/app.js'
},
app3: {
script: './app3/app.js'
}
}
})
loadGruntTasks(grunt)
grunt.registerTask('default', ['concurrent:runAll'])
}
Update
If I use grunt-watch instead of grunt-nodemon, only the app whose code I modified will restart. The problem is that grunt-watch only knows to run node app.js which gives an error because the app is already running. Is there a way to make grunt-watch kill the node process and restart it?

I think the answer could be fairly simple. Nodemon has an ignore option. For each of your three applications nodemon grunt configurations you can configurate them to ignore the directories of the other applications. That way they only kick off their restart when their own files are changed and not those of other projects. Let me know how that goes. :) Specifics about setting up the ignore section of config can be found in both nodemons documentation and grunt-nodemons documentation.

Patrick Motard's answer made me think about what directory nodemon was running in and how it was observing the files for changes. It appears that since I started grunt inside the parent directory of all the node apps that each nodemon process was looking for changes in all of those directories. So I set the working directory of the nodemon processes to the corresponding directory for each app using the options.cwd setting. That seemed to fix it. Here is the working solution:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concurrent: {
runAll: {
tasks: ['nodemon:app1', 'nodemon:app2', 'nodemon:app3'],
options: {
logConcurrentOutput: true
}
}
},
nodemon: {
app1: {
script: 'app.js',
options: {
cwd: './app1'
}
},
app2: {
script: 'app.js',
options: {
cwd: './app2'
}
},
app3: {
script: 'app.js',
options: {
cwd: './app3'
}
}
}
})
loadGruntTasks(grunt)
grunt.registerTask('default', ['concurrent:runAll'])
}

Related

Grunt: How do I run seperate processes for CSS (sass, concat, minify) and JS (concat, minify)

I'm looking at the grunt watch documentation but I can see how to run a separate process for my javascript files. Below is what I have for CSS:
GruntFile.js
module.exports = function(grunt) {
grunt.initConfig({
// running `grunt sass` will compile once
sass: {
dist: {
options: {
style: 'expanded'
},
files: {
'./public/css/sass_styles.css': './src/sass/sass_styles.scss' // 'destination': 'source'
}
}
},
// bring in additonal files that are not part of the sass styles set
concat: {
dist: {
src: [
'public/css/datepicker.css',
'public/css/jquery.tagsinput.css',
'public/css/sass_styles.css',
'application/themes/japantravel/style.css'
],
dest: 'public/css/all.css',
},
},
// running `grunt cssmin` will minify code to *.min.css file(s)
cssmin: {
minify: {
expand: true,
cwd: "public/css/",
src: ["all.css", "!*.min.css"],
dest: "public/css/",
ext: ".min.css"
}
},
// running `grunt watch` will watch for changes
watch: {
files: ["./src/sass/*.scss", "./src/sass/partials/*.scss"],
tasks: ["sass", "concat", "cssmin"]
}
});
// load tasks
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-watch");
};
As you can see I have tasks for CSS ["sass", "concat", "cssmin"], but I want to do separate tasks for separate files (js) - concat and minify - and listen for changes (watch). Can someone point me in the correct direction, I'm not really sure what I should be searching for. Is this something that watch can handle, or is there another plugin? I'm a little new to grunt so still trying to figure out how to use it. Thanks
You can use 'grunt-concurrent' for that, you can define multiple tasks with it. In combination with watch sets you will have the proper solution. https://github.com/sindresorhus/grunt-concurrent
# to install:
npm install grunt-concurrent --save-dev
And this will be your adjusted function then.
Remember, you still have to set some uglify and jshint properties! But I believe that's not the issue here.
module.exports = function(grunt) {
grunt.initConfig({
/* .. */
// running `grunt watch` will watch for changes
watch: {
// Use 'sets' like this, just make up a name for it:
watchCss: {
files: ["./src/sass/*.scss", "./src/sass/partials/*.scss"], // Directory to look for changes
tasks: ["concurrent:taskCss"] // Tasks you want to run when CSS changes
},
watchJs: {
files: ["./src/js/**/*.js"], // Directory to look for changes
tasks: ["concurrent:taskJs"] // Tasks you want to run when JS changes
}
},
concurrent: {
taskCss: ["sass", "concat", "cssmin"], // define the CSS tasks here
taskJs: ["jshint", "concat", "uglify"] // define the JS tasks here
},
});
// load tasks
grunt.loadNpmTasks("grunt-contrib-sass");
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-cssmin");
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks('grunt-contrib-jshint'); // Added
grunt.loadNpmTasks('grunt-contrib-uglify'); // Added
grunt.loadNpmTasks("grunt-concurrent"); // Added
// register tasks (note: you can execute sets from concurrent)
grunt.registerTask('default', ["concurrent:taskCss", "concurrent:taskJs"]);
grunt.registerTask('css', ["concurrent:taskCss"]);
grunt.registerTask('js', ["concurrent:taskJs"]);
};
To watch for changes:
grunt watch
# if a css file is changed, only the css tasks are performed
You can also execute a task from the prompt directly, for example:
grunt js
# This will only execute the registered task 'js'
# In this case that task points to 'concurrent:taskJs' wich will run jshint, concat and uglify
To install uglify and jshint:
https://github.com/gruntjs/grunt-contrib-uglify
https://github.com/gruntjs/grunt-contrib-jshint
npm install grunt-contrib-uglify --save-dev
npm install grunt-contrib-jshint --save-dev

How can I run a Node.js app using grunt-contrib-watch?

For example, I have a project folder "myProject" with the following files:
/myProject/app.js
/myProject/foo.json
Is there a way to setup grunt-contrib-watch to run app.js any time foo.json is modified?
Something like:
shell: {
runapptask: {
command: [
'node /myPorject/app.js'
]
}
},
watch: {
runapp: {
files: ['/myproject/foo.json'],
tasks: ['shell:runapptask']
}
}

grunt throw "Recursive process.nextTick detected"

I'm running Lion 10.9.2 with nodejs v0.10.26
I want to setup an automated compilation on sass files and a live reload with grunt, nothing complicated but...
When running grunt watch I get the following error
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
util.js:35
var str = String(f).replace(formatRegExp, function(x) {
^
RangeError: Maximum call stack size exceeded
here is the Gruntfile.js
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dist: {
files: {
'assets/css/styles.css': 'assets/sass/styles.scss'
}
}
},
watch: {
all: {
files: 'index.html', // Change this if you are not watching index.html
options: {
livereload: true // Set livereload to trigger a reload upon change
}
},
css: {
files: [ 'assets/sass/**/*.scss' ],
tasks: [ 'sass' ],
options: {
spawn: false
}
},
options: {
livereload: true // Set livereload to trigger a reload upon change
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('watch', [ 'watch']);
grunt.registerTask('default', [ 'sass', 'watch' ]);
};
and here is the package.json
{
"name": "application",
"version": "0.0.1",
"private": true,
"devDependencies": {
"grunt": "~0.4.2",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-sass": "~0.7.3"
}
}
I finally figured out a similar problem I was having with SASS. I was using
grunt.registerTask('sass', [ 'sass']);
The trick was that Grunt doesn't seem to like the repetition in names. When I switch to
grunt.registerTask('styles', [ 'sass']);
Everything worked as it should.
Just had this problem. Resolved it by removing grunt.registerTask('watch', [ 'watch']);
I just fixed a similar error "Recursive process.nextTick detected" causing by command: grunt server
The solution? Use sudo grunt serve instead
you could try this one, it fixed the issue for me, working with Yeoman 1.3.3 and Ubuntu 14.04 Grunt watch error - Waiting...Fatal error: watch ENOSPC
I was getting error in even trying to install grunt. Running npm dedupe solved my problem as answered here: Grunt watch error - Waiting...Fatal error: watch ENOSPC
Alternative solution: check your watch for an empty file argument.
Here's an excerpt of my gruntfile
watch: {
all: {
options:{
livereload: true
},
files: ['src/scss/*.scss', 'src/foo.html',, 'src/bar.html'],
tasks: ['default']
}
}
In my case, I could recreate the original poster's error on demand with the empty argument above.

More than 1 requirejs task in grunt for different optimization options

I use r.js to cobble together all the js code in my SPA into 1 file. I use grunt's `grunt-contrib-requirejs' task for this, with the following:
requirejs: {
compile: {
options: {
name: 'app',
out: 'build/js/app.js',
baseUrl: 'app',
mainConfigFile: 'config/main.js',
preserveLicenseComments: true,
optimize: "none"
}
}
}
I also use a build task that zips the build folder into a zip file for me to send to our company's change management folks.
I would like to have two requirejs tasks - one that uglifies (for sending to CM) and one that doesn't (during development). Is this possible? I tried creating a new task with a different name and grunt yelled at me... should be simple. Is this possible? Are there any reasons not to do this?
Thanks in advance!
Actually it is very simple:
requirejs: {
compile: {
options: {
...
optimize: "none"
}
},
compileForProduction: {
options: {
...
optimize: "uglify2"
}
}
}
(options are same as yours, with any diffs between the two that are required, e.g. optimize)
Run it with:
grunt requirejs:compileForProduction
or in Gruntfile.js:
grunt.registerTask("prod", ["requirejs:compileForProduction"]);
and:
grunt prod

Configure grunt watch to run Jasmine tests against an app using requirejs

In an attempt to level up my general coding skills... and to learn something new.
I've started attempting to wire up a front end only solution consisting of
Durandal
Jasmine - [added via npm]
Grunt Watch to monitor & run my tests as my code files change - [added via npm]
Feel free to correct me, as this is all based on my experimentation in the last 2 days. Most of this is new to me. My goal is to have something similar as to what angular has with karma.
Now I am aware that that the Durandal project (comes with a custom spec runner, as found in the github solution)
My setup:
gruntfile.js
module.exports = function(grunt) {
var appPath = 'App/viewmodels/*.js';
var testPath = 'Tests/**/*.js';
grunt.initConfig({
jasmine: {
pivotal: {
src: appPath,
options: {
specs: testPath,
template: require('grunt-template-jasmine-requirejs'),
templateOptions: {
requireConfigFile: 'SpecRunner.js'
}
}
}
},
jshint: {
all: [testPath, appPath],
options: {
curly: true
}
},
watch: {
files: [testPath, appPath],
tasks: ['jshint','jasmine']
}
});
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['jshint','jasmine']);
};
SpecRunner.js
require.config({
paths: {
jquery: 'Scripts/jquery-1.9.1',
knockout: 'Scripts/knockout-2.3.0'
},
shim: {
knockout: {
exports: "ko"
}
}
});
When I run grunt, I get a Illegal path or script error: ['plugins/http']
(I've sorted out the ko issue in the screenshot)
Question:
How would i go about setting up my gruntfile to require any dependencies. I'm quite new to require, and I'm not sure how to configure it to make my tests aware of where to find things like 3rd party libraries and other custom js files for that matter
SpecRunner require.config is missing Durandal specific path information. If you set the baseUrl to 'App' then the paths below matches the HTML samples or StarterKit layout. If your layout is different you'd have to adjust this accordingly.
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-2.3.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1'
}
});

Resources