Use both grunt-contrib-less and grunt-nodemon - gruntjs

It seems that when the nodemon running ,the other tasks will be pending and not runned. How can I use both of them? or whether I can use nodemon to watch less files and compile them?
Here is my Gruntfile.js:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
nodemon: {
dev: {
options: {
file: 'app.js',
nodeArgs: ['--debug'],
env: {
PORT: '3000'
}
}
}
},
less: {
development: {
options: {
paths: ['./public/less'],
yuicompress: true
},
files: {
'./public/css/test.css': './public/less/test.less'
}
}
},
watch: {
files: "./public/less/*.less",
tasks: ['less']
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-nodemon');
grunt.registerTask('default', ['less','watch']);
};

What you're looking for is grunt-concurrent, a task that allows you to run multiple tasks asynchronously and it's incredibly common for blocking tasks such as watch or nodemon.
https://github.com/sindresorhus/grunt-concurrent
As for nodemon, a prime example of this is located directly on the github page for grunt-nodemon using grunt-concurrent under the section 'Advanced Usage'.
https://github.com/ChrisWren/grunt-nodemon#advanced-usage
Hope this is what you're looking for.

Related

Grunt index file not running

I am trying to get my index.html at the root of my app (app/index.html) running with grunt from I file I inherited.
My grunt file is as follows:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass_directory_import: {
your_target: {
files: {
src: ['css/sass/parts/_all.scss']
},
},
},
connect: {
server: {
options: {
port: 9000,
hostname: 'localhost',
base: ['./'],
keepalive: true,
open: {
target: 'http://localhost:9000'
}
}
}
},
sass: {
dist: {
options: {
loadPath: require('node-bourbon').includePaths,
sourceMap: true
},
files: {
'css/style.css' : 'css/sass/style.scss',
'css/style-ie.css' : 'css/sass/style-ie.scss'
}
},
},
watch: {
sass: {
files: 'css/sass/**/*.scss',
tasks: ['sass_directory_import','sass']
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass-directory-import');
grunt.loadNpmTasks('grunt-contrib-connect');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default',['watch', 'connect:server']);
grunt.registerTask('build',['sass', 'uglify']);
};
I want index to appear under the port: http://localhost:9000 but when I run the default watch task, only get the sass files being watched for changes and nothing else. How do I get grunt to run the file under the given port? I have only used Gulp before and am not finding grunt very easy to work with. Is there a grunt server/connect task that does not have to be installed?

Grunt run task with override config

I always used gulp for all my tasks automation, but in our current project we use grunt and I can't figure out how to make very simple thing:
grunt.initConfig({
watch: {
scripts: {
files: '**/*.js',
tasks: ['karma:watch:run'],
}
},
myWatch: {
scripts: {
files: '**/*.js',
tasks: ['do_my_own_task_but_not_karma'],
}
}
});
//current task
grunt.registerTask('default', ['watch']);
//doesn't work
grunt.registerTask('myWatchTask', ['myWatch']);
Basically I just want to override current watch config for my own custom task, because I don't want karma to run tests each time I change js file.
You need to add an new configuration within the watch configuration object:
grunt.initConfig({
watch: {
main: {
scripts: {
files: '**/*.js',
tasks: ['karma:watch:run'],
}
},
myWatch: {
scripts: {
files: '**/*.js',
tasks: ['do_my_own_task_but_not_karma'],
}
}
},
});
Then you can run grunt watch:main or grunt watch:myWatch, see these docs.
If you want to have something that is watched always you can add it to the root of the watch configuration object.
grunt.initConfig({
watch: {
files: '**/always.js',
tasks: ['always'],
main: {
scripts: {
files: '**/*.js',
tasks: ['karma:watch:run'],
}
},
myWatch: {
scripts: {
files: '**/*.js',
tasks: ['do_my_own_task_but_not_karma'],
}
}
},
});
now grunt watch:myWatch will run it's dedicated config and the config in the root of the watch configuration object.

Get Grunt to upload files after watch is triggered

I am working on a site that uses SCSS. We have grunt watching those files to convert them to css but each time we make a change we have to tab over to the css file and upload. Maybe not a big deal but over time on different projects it adds up.
I would like the watch process to run ftpush once it see's a change but the only times I've got it to work it stays on ftpush which means we have to exit grunt then run it again. It would be helpful if after the upload os complete(or a specific time passes) it resumes the watch task.
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
options: {
loadPath: ['bower_components/foundation/scss'],
sourceMap: true
},
dist: {
options: {
style: 'expanded'
},
files: {
'assets/css/app.css': 'assets/scss/app.scss'
}
}
},
ftpush: {
build: {
auth: {
host: 'OUR HOST',
port: 21,
authKey: 'key1'
},
src: '../vhc-master',
dest: '/var/www/html/vhc/dev/wp-content-themes/vhc-master'
}
},
watch: {
scripts: {
files: ['Gruntfile.js'],
tasks: ['ftpush'],
options: {
interrupt: true,
reload: true
}
},
sass: {
files: 'assets/scss/*.scss',
tasks: ['sass']
}
}
});
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-ftpush');
grunt.registerTask('build', ['sass']);
grunt.registerTask('deploy', ['ftpush']);
grunt.registerTask('default', ['build','watch']);
}

Set up grunt to build Jekyll site, serve & livereload

I have a simple Jekyll site, and am using grunt to compile LESS files.
I want to build in the ability to continue compiling .less files, building the jekyll site & serving it locally. I also have a task to watch and copy compiled css files into the jekyll _site folder.
However the Grunftile I have at the moment isn't quite working:
module.exports = function (grunt) {
grunt.initConfig({
// compile set less files
less: {
development: {
options: {
paths: ["assets/less"],
yuicompress: true,
compress: true
},
files: {
"assets/css/site.css": ["assets/less/*.less", "!assets/less/_*.less"]
}
}
},
// watch changes to less files
watch: {
styles: {
files: ["less/**/*"],
tasks: ["less", "copy:css"]
},
options: {
livereload: true,
spawn: false,
},
},
// copy compiled css to _site
copy: {
css : {
files: {
cwd: './assets/css/',
src: 'site.css',
dest: './_site/assets/css',
expand: true
}
}
},
// run jekyll command
shell: {
jekyll: {
options: {
stdout: true
},
command: 'jekyll build'
}
},
// jekyll build
jekyll: {
files: [
'*.html', '*.yml', 'assets/js/**.js',
'_posts/**', '_includes/**'
],
tasks: 'shell:jekyll',
options: {
livereload: true
}
},
exec: {
server: {
command: 'jekyll serve -w'
}
},
concurrent: {
options: { logConcurrentOutput: true },
server: {
tasks: ['watch', 'exec:server']
}
}
});
// Load tasks so we can use them
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks("grunt-contrib-less");
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-concurrent');
// the default task will show the usage
grunt.registerTask("default", "Prints usage", function () {
grunt.log.writeln("");
grunt.log.writeln("Using Base");
grunt.log.writeln("------------------------");
grunt.log.writeln("");
grunt.log.writeln("* run 'grunt --help' to get an overview of all commands.");
grunt.log.writeln("* run 'grunt dev' to start watching and compiling LESS changes.");
});
grunt.registerTask("dev", ["less:development", "watch:styles", "copy:css", "shell:jekyll", "concurrent:server"]);
};
It's probably better to have Grunt also building Jekyll, using grunt-jekyll https://github.com/dannygarcia/grunt-jekyll. I suspect you're having issues with Jekyll cleaning the output directory after your copy task has placed your compiled LESS output there, so it's important your tasks are run in the correct sequence.
There's an excellent Yeoman generator with a complete Jekyll / Grunt workflow that's also worth checking out; https://github.com/robwierzbowski/generator-jekyllrb and if you don't want to use Yeoman then you will at least find some helpful pointers in the Gruntfile https://github.com/robwierzbowski/generator-jekyllrb/blob/master/app/templates/Gruntfile.js

Grunt - lint only modified files using grunt-newer

I'm running a Grunt task that uses Concurrent to run both Nodemon and Watch/Livereload. On default load, I lint and launch Concurrent. I would also like to set up a Watch to lint individual files on change. Currently, all files are linted when any one file is changed.
I have examined a similar question on StackOverflow and decided to go with grunt-newer as a potential solution. In my implementation below, however, the 'newer' prefix doesn't seem to do anything. How can I fix this so that only changed files are linted?
module.exports = function(grunt) {
//load all dependencies
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concurrent: {
dev: {
options: {
logConcurrentOutput: true
},
tasks: ['watch', 'nodemon']
}
},
jshint: {
files: ['Gruntfile.js', 'client/src/*.js', 'server/**/*.js'],
options: {
'-W030': true,
'-W083': true,
globals: {
console: true,
module: true,
document: true
}
}
},
watch: {
all: {
files: ['<%= jshint.files %>'],
tasks: ['newer:jshint']
},
frontend: {
files: ['client/**/*.{css,js,html}'],
options: {
livereload: true
}
}
},
nodemon: {
dev: {
options: {
file: 'server/server.js',
watchedFolders: ['server']
}
}
}
});
grunt.registerTask('test', ['jshint']);
grunt.registerTask('default', ['jshint', 'concurrent']);
};
I was having the same problem and finally figured it out. The solution is hidden deep in the documentation and very misleading with the spawn option in the code sample: https://github.com/gruntjs/grunt-contrib-watch#compiling-files-as-needed
Your config file should remain the same as you have it in your question, but you need to add a listener to the watch event. I recommend the 'robust' option they provide (modified for you specific task config). Place this code just above the call to grunt.initConfig and after you require calls.
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
// Modified to point to jshint.files as per the task example in the question.
grunt.config('jshint.files', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
Add the nospawn option to the all watch task. This is what is misleading in in the documentation. It mentions it should be disabled if you want dynamically modify your config but basically prevents it from working with newer unless it's set to true:
watch: {
all: {
files: ['<%= jshint.files %>'],
tasks: ['newer:jshint'],
options: {
nospawn: true,
}
},
...
NOTE: If you modify your grunt file while it's running then it will lint all files, not sure why it does this but then it gets stuck and will just keep linting everything for all changes you make. I just took out the 'gruntfile.js' from the list of files that should be linted to avoid it.

Resources