Gruntfile.js - Throwing error 'Recursive process.nextTick detected" - javascript

I have defined a simple Gruntfile.js per the official instructions and yet I am getting a warning when I run the grunt watch ('$ grunt watch') or grunt default task ('$ grunt ').
The error is:
(node) warning: Recursive process.nextTick detected. This will break
in the next version of node. Please use setImmediate for recursive
deferral.
I have read the related StackOverflow question and answer here: grunt throw "Recursive process.nextTick detected", but that didn't resolve my issue.
My Gruntfile.js is:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';'
},
dist: {
src: ['client/app/**/*.js'],
dest: 'client/dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
jshint: {
files: ['client/app/**/*.js', 'server/**/*.js'],
options: {
// options here to override JSHint defaults
globals: {
jQuery: true,
console: true,
module: true,
document: true
}
}
},
watch: {
files: ['<% jshint.files %>'],
tasks: ['jshint']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['watch']);
grunt.registerTask('test', ['jshint']);
grunt.registerTask('build-dev', ['jshint', 'concat']);
grunt.registerTask('build', ['jshint', 'concat', 'uglify']);
};

OK. I figured it out. And dagnabbit, the bug was in the same Gruntfile that I copied hither from thither.
Node did NOT like the watch instructions to reference the jshint.files property and then call the jshint task. So instead, I put the files in explicitly as follows. After changing the following lines (with context):
watch: {
files: ['client/app/**/*.js', 'server/**/*.js'],
tasks: ['jshint']
}
the grunt watch and default tasks (the default task was performing the watch task), it worked without any warnings!

So I know this question has been answered, but I'll share my insights into this error as it proved to be a colossal waste of time.
Here's my original Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
dev: {
files: ['**/*.js', 'public/stylesheets/**/*.scss'],
tasks: ['express:dev'],
options: {
spawn: false
}
}
},
express: {
dev: {
options: {
script: 'server.js',
node_env: 'development'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express-server');
grunt.registerTask('default', ['express:dev', 'watch']);
};
In a similar vain to Chad, I resolved the issue by removing js files from my watch task, which restarts Express. The below configuration of the aforementioned task works fine for me:
watch: {
dev: {
files: ['public/stylesheets/**/*.scss'],
tasks: ['express:dev'],
options: {
spawn: false
}
}
},

Related

Uglify not working with Grunt Watch

I have a pretty basic setup with sass, watch and uglify but for some reason I can't get watch to detect when a js file is saved. It works fine for SCSS/CSS (compiles and reloads.) If I run 'grunt uglify' it bundles my JS files, and if watch is running (in another console instance) it will detect it and trigger the reload.
I've tried lots of combinations and I have a feeling it's something really dumb I'm doing/not doing but I'm just not seeing it.
my gruntfile.js:
module.exports = function(grunt) {
grunt.registerTask('default', ['sass', 'uglify']);
grunt.initConfig({
sass: {
dist: {
options: {
style: 'expanded'
},
files: { 'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/main.css': 'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/main.scss' }
}
},
uglify: {
my_target: {
files: {
'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/js/site.js': [
'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/lib/jquery/dist/jquery.js',
'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/lib/*.js'
]
}
}
},
watch: {
options: {
livereload: 35729,
},
html: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/Views/*.cshtml'],
},
sass: {
options: {
livereload: false
},
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/*.scss'],
tasks: ['sass']
},
css: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/main.css'],
tasks: []
},
scripts: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/js/site.js'],
tasks: ['uglify']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
};
Look at your watch config:
scripts: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/js/site.js'],
tasks: ['uglify']
}
You are only watching for a single js files changes called site.js. To watch all your sources use this config:
scripts: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/lib/*.js'],
tasks: ['uglify']
}
Use the same pattern as in the uglify config. I assumed you are not going to modify jquery itself.

Grunt / Babel error: Unable to write "dist" file (Error code: EISDIR)

I am new to Grunt and all its plugins, but I want to learn and setup some awesome front-end tools. With that said, I have been following the Grunt docs and some's similar issue with Grunt and Babel via Github, but I seem to keep getting the following traceback:
Running "babel:dist" (babel) task
Warning: Unable to write "dist" file (Error code: EISDIR). Use --force to continue.
Aborted due to warnings.
Any clearer explanation to this newbie would be HIGHLY appreciated. I'm new to programming in JS and setting up DevOps, so some helpful tips and best practices are encouraged.
Setup:
js_practice/ (Root Project)
|----package.json
All the distributions and packages
|---node_modules/
Server-Side (Node) support
|---es6/
| ------ test.js
|---dist/
Client (browser) support
|----public/
|---es6/ (this is within the public folder)
| ----- test2.js
|---dist/ (this is within the public folder)
Here is my current code:
Grunt file.js
module.exports = function(grunt) {
// All of your Grunt code must be specified inside this function!
// Setup configuration...
// Load tasks...
// Define tasks...
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
babel: {
options: {
sourceMap: true,
presets: ['babel-preset-es2015']
},
dist: {
files: [
// Node source
{
src: ['es6/**/*.js'],
dest: 'dist'},
// Browser source
{
src: ['public/es6/**/*.js'],
dest: 'public/dist'},
],
},
},
browserify: {
dist: {
options: {
transform: [["babelify", { "stage": 0 }]]
},
files: {
"build/bundle.js": "src/main.js"
}
}
},
jshint: {
scripts: {
src: ['scripts/**.js', 'lib/**.js']
},
tests: { // We can have more than one jshint task, this ones called `jshint:tests`
src: 'tests/**.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
},
scripts: {
expand: true,
cwd: 'scripts/',
src: '**.js',
dest: 'build/',
ext: '.min.js'
}
},
watch: {
scripts: {
files: ['**/*.js'],
tasks: ['jshint'],
},
styles: {
files: 'styles/**.less',
task: 'less:styles'
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-babel');
grunt.registerTask('default', ['babel','browserify','jshint']);
grunt.registerTask('build', ['jshint', 'uglify']);
};
Just expanding on what I said in the comments
Any clearer explanation to this newbie would be HIGHLY appreciated.
Nodejs is trying to write a file called dist, but produces an error because a directory with this name exists.
The cause of this is found in the babel task.
files: [{
src: ['es6/**/*.js'],
dest: 'dist'
},
// Browser source
{
src: ['public/es6/**/*.js'],
dest: 'public/dist'
}]
You have to tell Babel to take each file in es6/, transform them and place the new files in the dist/ folder. As it stand now, the transformer tries to create a file called dist. Rewriting it to
files: [{
expand: true,
cwd: 'es6/'
src: ['**/*.js'],
dest: 'dist/'
},
// Browser source
{
expand: true,
cwd: 'public/es6/'
src: ['**/*.js'],
dest: 'public/dist/'
}]
should yield a better result, but play around with it. Like I mentioned, I haven't used Grunt in a while. Take a look at the documentation on building the files object
And like I said in the comments, use jshint or other such tools (eslint is all the hype...) to keep your own code neat. Don't waste time by running a jshint task on lib files that you probably don't want to fix yourself anyway. And always run jshint on the source files, not files that are transformed by babel or browserify. It's just a tool to help you write better code, not some generator.

Grunt Watch Task Not Triggering Uglify Task

I'm running a pretty straightforward workflow with Grunt, operating inside MAMP. I'm using a watch task to trigger a Sass task, which runs two sub-tasks (placing expanded and compressed stylesheets in different directories), and minifying/concatenating JavaScript files. The Sass task works without issue, but the Watch task will not see any JavaScript file changes to trigger the Uglify task. Here's my Grunt.js file
module.exports = function(grunt){
grunt.initConfig({
pkg : grunt.file.readJSON('package.json'),
//Sass task
sass:{
dev: {
options: {
style: 'expanded',
sourcemap: 'none'
},
files: {
//Destination, Source
'human-readable/style-expanded.css': 'sass/style.scss',
'human-readable/bootstrap-min.css': 'sass/bootstrap.scss'
}
},
prod:{
options:{
style: 'compressed',
sourcemap: 'none'
},
files:{
//Destination, Source
'style.css': 'sass/style.scss',
'css/bootstrap.min.css': 'sass/bootstrap.scss'
}
}
},
//Uglify task
uglify:{
options:{
mangle: false,
screwIE8: true
},
my_target:{
files:{
//Destination, Source
'js/main.min.js': ['human-readable/main.js','js/bootstrap.min.js']
}
}
},
//Watch task
watch: {
css: {
files: '**/*.scss',
tasks: ['sass']
},
scripts: {
files: '**/*.js',
tasks: ['uglify']
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['watch']);
}
Ideas?
may be you are trying to watch two things at the same time, that might be the problem, try the grunt-concurrent module, it allows you to run grunt tasks concurrently / in parallel:
grunt.loadNpmTasks('grunt-concurrent');
grunt.initConfig({
...
concurrent: {
tasks: ['watch:css', 'watch:script']
}
...
grunt.registerTask('default', ['concurrent']);
...

Grunt task duplicate key

I have a grunt file with tasks and jshint giving me a warning for duplicate keys on below:
clean: ['public', 'build', 'css/main.css', 'css/print.css'],
clean : {
aftertest :['js/libs']
},
How can I make this in one key, so that by default it runs ['public', 'build', 'css/main.css', 'css/print.css']?
You should use different targets for this.
grunt.initConfig({
clean: {
build: ['public', 'build', 'css/main.css', 'css/print.css'],
aftertest: ['js/libs']
}
});
Then in your build alias you might want to use it like so:
grunt.registerTask('build', ['clean:build', 'stylus', 'jade', 'jshint']);
Whenever you have more than a single target for one task, it's best to explicitly name them so that you'll know, in the future, what each target's purpose is.
The error it's because the object you are passing to grunt.initConfig has two keys with the same name.
This is a Gruntfile.js example for gjslint task
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint', 'qunit']
},
gjslint: {
options: {
flags: [
'--nojsdoc'
],
reporter: {
name: 'console'
}
},
app: {
src: ['www/app/**/*.js']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-gjslint');
grunt.registerTask('build', 'Grunt build taskt...', function() {
grunt.log.write('you can log here some stuff...').ok();
});
};

Alternate grunt.js tasks for development/production environments

I would really love to be able to have a development grunt file and using the same file an production version of the script.
I have tried the suggestion on SO but my script will just fail when trying to call a dev/prod argument. I believe that the answer is for an older version of grunt, or maybe the plugins I am using.
module.exports = function (grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
compass: {
dev: {
options: {
config: 'config.rb',
force: true,
livereload: true
}
}
},
uglify: {
build: {
src: ['docroot/js/*.js', 'docroot/components/**/*.js'],
dest: 'docroot/dis/main.min.js'
}
},
watch: {
options: {
dateFormat: function(time) {
grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());
grunt.log.writeln('Waiting for more changes...');
},
livereload: true
},
sass: {
files: ['docroot/sass/*.scss'],
tasks: ['compass:dev']
},
/* watch and see if our javascript files change, or new packages are installed */
js: {
files: '<%= uglify.build.src %>',
tasks: ['uglify']
},
/* watch our files for change, reload */
livereload: {
files: ['*.html', 'docroot/css/*.css', 'docroot/img/*', 'docroot/js/{main.min.js, plugins.min.js}'],
options: {
livereload: true
}
}
}
});
grunt.registerTask('default', 'watch');
};
Really, so long as I can get two version running by calling them with, for example:
grunt //local
grunt prod //live
then I can play around with the scripts and what to load.
You can also just register a task that calls an array of tasks
grunt.registerTask('prod', ['tasks1','task2']);
before your default task, that would be
$ grunt prod

Categories