Grunt seems to skip some tasks on first run - gruntjs

Please forgive my grunt noobiness.
I have grunt 0.4 installed correctly and working, and I'm loving it.
I cannot understand however, why my default task always skips some sub-tasks, on the first time.
Here's the relevant part of Gruntfile:
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
copy: {
main: {
files: [
{src: ['src/**'], dest: 'temp/'} // includes files in path and its subdirs
]
}
},
uglify: {
main: {
files: grunt.file.expandMapping(['temp/**/*.js', '!temp/**/*min.js'], './')
}
},
imagemin: {
main: {
files: grunt.file.expandMapping(['temp/**/*.png', 'temp/**/*.jpg'], './')
}
},
compress: {
main: {
options: {
archive: 'archive.zip'
},
files: [
{expand: true, cwd: 'temp/src/', src: ['**'], dest: './'} // makes all src relative to cwd
]
}
},
clean: ["temp", "archive.zip"]
});
// Load the plugins
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-contrib-clean');
// Default task(s).
grunt.registerTask('default', ['clean', 'copy', 'uglify', 'imagemin', 'compress']);
grunt.registerTask('test', ['clean', 'copy', 'uglify']);
On the first run of grunt, both uglify and imagemin tasks do not process (and output) anything. If I launch it again it all works fine. If I manually delete the "temp" folder and relauch grunt, uglify and imagemin do not do anything again.
Please help me finding what I am doing wrong.
Node is version 0.8.2, gruntcli 0.1.6, grunt 0.4.0
Thanks for reading

the reason for that, is that grunt.file.expandMapping (which you use in both tasks) is running when the gruntfile is loaded and NOT when the actual task is run. so files which are generated through other tasks will not be availableto your imagemin/uglify-task.
you should use the files-object the same-way you do in your other tasks!

Related

Gruntfile.js not running certain packages

can you please take a look at the following Gruntfile to see if you can determine why it isn't running cssnano and autoprefixer?
Grunt is currently watching my project and with each save grunt-sass compiles fine but neither grunt-cssnano or autoprefixer are doing their thing and no errors are reported.
Done, without errors.
Completed in 1.906s at Wed Nov 25 2015 13:12:18 GMT+0000 (GMT Standard Time) - Waiting...
File "sass\styles.scss" changed.
Running "sass:dist" (sass) task
I figure I've done something wrong with grunt-contrib-watch setup (specifically the css part) but that's just a guess.
My project folder looks like so
dist
css
styles.css
node_modules (includes all relevant packages)
sass
styles.css
Gruntfile.js
package.json
And my Gruntfile is as follows
module.exports = function (grunt) {
grunt.initConfig({
sass: {
options: {
sourceMap: false
},
dist: {
files: {
'dist/css/styles.css': 'sass/styles.scss'
}
}
},
postcss: {
options: {
map: {
inline: false,
annotation: 'dist/css/maps/'
},
processors: [
require('autoprefixer')({
browsers: 'last 2 versions'
}),
require('cssnano')()
]
},
dist: {
src: 'dist/css/styles.css'
}
},
watch: {
sass: {
files: 'sass/*.scss',
tasks: ['sass']
},
css: {
files: 'dist/css/styles.css',
tasks: ['cssnano', 'autoprefixer']
}
},
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-postcss');
grunt.loadNpmTasks('grunt-cssnano');
grunt.registerTask('default', ['watch', 'sass', 'postcss:dist', 'cssnano', 'autoprefixer']);
};
registering a task like you do :
grunt.registerTask('default', ['watch', 'sass', 'postcss:dist', 'cssnano']);
will execute the tasks one by one. So in your case, only the watch task will be executed because it "never ends" till you finish it. So the sass, postcss:dist, cssnano wont be reached.
So in your case it will execute the watch task only, which will watch the *.scss files to execute the sass task and watch the style.css to execute the cssnano and autoprefixer task.
But these 2 last tasks aren't defined in your config, so it won't do anything.
To solve your problem, remove the tasks from your default registered task because they aren't used :
grunt.registerTask('default', ['watch']);
And add a config for each missing task. for example:
cssnano: {
options: {
sourcemap: true
},
dist: {
files: {
'dist/css/styles.min.css': 'dist/css/styles.css'
}
}
},
//and same for autoprefixer
With a lot more trial and error it looks like I have a solution. The below file now runs Sass, cssnano, autoprefix and watch. Sass, cssnano and autoprefix packets (and I assume any others that are added in future) will do their thing in grunt.initConfig while and at the bottom of the file registerTask takes care of watch.
More work is need to figure out how to create other registerTasks but that's for another day.
Thanks to Mian who set me on the right track.
module.exports = function (grunt) {
grunt.initConfig({
sass: {
options: {
sourceMap: false
},
dist: {
files: {
'dist/css/styles.css': 'sass/styles.scss'
}
}
},
postcss: {
options: {
map: {
inline: false,
annotation: 'dist/css/maps/'
},
processors: [
require('autoprefixer')({
browsers: 'last 2 versions'
}),
require('cssnano')()
]
},
dist: {
src: 'dist/css/styles.css'
}
},
watch: {
sass: {
files: 'sass/*.scss',
tasks: ['sass', 'postcss']
},
},
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-postcss');
grunt.loadNpmTasks('grunt-cssnano');
grunt.registerTask('default', ['watch']);
};

No images being compressed using grunt-contrib-imagemin

I'm having trouble using grunt-contrib-imagemin, insofar as I can't get it to compress any images.
Here's my Gruntfile.js
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
dist: {
src: [
'css/{base,global,medium,large}.css', // All CSS in the CSS folder
],
dest: 'css/build/production.css',
}
},
cssmin: {
build: {
src: 'css/build/production.css',
dest: 'css/build/production.min.css'
}
},
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'if3/images',
src: ['**/*.{png,jpg,gif}'],
dest: 'images/build'
}]
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-imagemin');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['concat', 'cssmin', 'imagemin']);
}
When I run grunt from the command line, each of concat and cssmin run fine, whereas imagemin - although running without errors - returns the following message.
Running "imagemin:dynamic" (imagemin) task
Minified 0 images (saved 0 B)
For info, my folder structure is as follows.
if3\
css\
*.css
images\
*.png
*.jpg
js\
*.js
node_modules\
etc.
Gruntfile.js
package.json
*.html
The image folder currently contains 7 PNG and 2 JPG files, but I can't figure out why it's not doing anything with them.
Any help much appreciated.
Thanks
your src-properties in your concat and cssmin tasks do not contain if3. your imagemin config does. removing that should probably help...
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images',
src: ['**/*.{png,jpg,gif}'],
dest: 'images/build'
}]
}
}
you don't need use: dynamic {} or static {} and will works perfect.
see: Grunt imagemin running but not minifying

Grunt SCSS - Not reloading

I am trying to achieve a smooth workflow.
my problem:
My JS modifications are shown and minified and the live reload works fine. When I make changes to my SCSS files they do not run under the run command:
grunt
or the grunt plugin:
grunt watch
It only works when I invoke:
grunt sass
This was the output from the 'grunt sass' console window:
Macintosh:grunt-test Neil$ grunt sass
Running "sass:dist" (sass) task
File "css/global.css" created.
Done, without errors.
Notes:
When I run 'grunt watch' on a sass file I have noticed that grunt runs the minification on the javascript for no reason. Surely this be invoked when that file or one of its dependencies is effected?
Gruntfile.js Contents:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
options: {
files: ['css/*.css'],
livereload: true
},
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
},
scripts: {
files: ['js/*.js', 'scss/*.scss'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
}
}
},
sass: {
dist: {
options: {
style: 'compressed'
},
expand: true,
cwd: 'scss/',
src: ['*.scss'],
dest: 'css/',
ext: '.css'
}
},
concat: {
// 2. Configuration for concatinating files goes here.
dist: {
src: [
'js/libs/*.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
uglify: {
build: {
src: 'js/build/production.js',
dest: 'js/build/production.min.js'
}
},
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images-lossy/',
src: ['**/*.{png,jpg,gif}'],
dest: 'images/'
}]
},
png: {
options: {
optimizationLevel: 7
}
},
jpg: {
options: {
progressive: true
}
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
// CONCATENATION PLUGIN
grunt.loadNpmTasks('grunt-contrib-concat');
// MINIFY PLUGIN
grunt.loadNpmTasks('grunt-contrib-uglify');
// IMG CRUSH PLUGIN
grunt.loadNpmTasks('grunt-contrib-imagemin');
// GRUNT WATCH PLUGIN
grunt.loadNpmTasks('grunt-contrib-watch');
// SASS LIBARY PLUGIN
grunt.loadNpmTasks('grunt-contrib-sass');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['sass','concat', 'uglify', 'imagemin', 'watch']);
};
I hope the above information helps. I have previously used Codekit, and it a really great app. I want to move to grunt but maybe my configuration file is incorrect I am close.
Any help would be greatly appreciated.
Neil
It looks like both of your issues occur within the watch configuration.
First, the reason the SASS task isn't working during watch is due to the files entry pointing to the wrong location. Your current files entry points to the "css" folder, but it should point to the "scss" folder, according to what you've specified in the actual "sass" task. In other words, your entry should be: files: ['scss/*.scss'].
css: {
files: ['scss/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
Second, the JavaScript minification occurs during the watch whenever a SASS file changes because you have it listed here:
scripts: {
files: ['js/*.js', 'scss/*.scss'], // <-- scss is covered here
tasks: ['concat', 'uglify'],
options: {
spawn: false,
}
}
Change it to files: ['js/*.js'], instead to have the watch task kick in for JavaScript files only.
Once you address those issues, if things are slightly working you might want to expand the patterns so that it covers all files in the subdirectories for your JavaScript, CSS, SASS, etc. For example, js/*.js includes all .js files under the js folder, while js/**/*.js covers the js folder and its subfolders. You can read more under the GruntJS "globbing patterns" documentation.
EDIT: here's how the updated watch should look like...
watch: {
options: {
livereload: true
},
// css is really for Sass
css: {
files: ['scss/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
},
// scripts will detect js changes
scripts: {
files: ['js/**/*.js'],
tasks: ['jshint', 'concat', 'uglify'],
options: {
spawn: false,
}
}
},
As mentioned, your individual tasks might need to use the ** pattern similar to what I've done with the "scripts" entry above: js/**/*.js

grunt - doesn't give any output

I have installed grunt-cli,grunt(local),grunt-init. Below is the simple grunt file to minify javascript files in source folder.
module.exports = function (grunt) {
grunt.initConfig({
min: {
dev: {
src: 'calculator/*.js',
dest: 'calculator.min.js'
}
}
});
};
when I run grunt, it does nothing, nor it gives any message out. nor does grunt --help or grunt --version..none of them seem to say anything. but if I dont' have grunt.js file it does complain about the grunt file not existing and help gives the details..
What you need to do is add a task that then calls min. To get it to run by just using grunt you must call this task default.
If you call it anything else (e.g. development, you must run grunt development)
You also need to make sure you have the necessary dependencies installed with npm. So min you probably want to minify JS with the gruntjs uglify module.
From the docs:
Install this plugin with this command:
npm install
grunt-contrib-uglify --save-dev
Once the plugin has been installed,
it may be enabled inside your Gruntfile with this line of JavaScript:
grunt.loadNpmTasks('grunt-contrib-uglify');
For example, here are some snippets from one of my Gruntfile.js
module.exports = function (grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
// configurable paths
var yeomanConfig = {
app: 'resources',
dist: 'dist'
};
grunt.initConfig({
yeoman: yeomanConfig,
uglify: {
dist: {
files: {
'<%= yeoman.dist %>/js/scripts.js': [
'<%= yeoman.app %>/js/lib/*.js'
],
'<%= yeoman.dist %>/js/output.js': [
'<%= yeoman.app %>/js/*.js'
],
}
}
},
});
grunt.registerTask('default', [
// 'jshint',
// 'test',
'uglify'
]);
The above sets up an uglify task and then the grunt.registerTask('default'.. part calls uglify when I run grunt.
The above was generated and used as part of the yeoman workflow.

Where are JSHint errors logged?

I just started messing around with Grunt. I have a basic implementation running successfully, minifying my code and running JSHint.
It says 0 files lint free, which I've gathered means that all of the files it's checking have lint.
However, I've been googling for an hour, and somehwat incredibly, cannot figure out where the hell these errors are being saved.
Do I need to specify a logfile in the grunt config? I don't see anything like that in the JSHint or grunt documentation.
Gruntfile below, taken pretty much straight from Grunt's "Getting Started". I pulled out qunit because I don't currently have any tests -
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
// define a string to put between each file in the concatenated output
separator: ';'
},
dist: {
// the files to concatenate
src: ['spin/**/*.js'],
// the location of the resulting JS file
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
// the banner is inserted at the top of the output
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
jshint: {
// define the files to lint
files: ['gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
// configure JSHint (documented at http://www.jshint.com/docs/)
options: {
// more options here if you want to override JSHint defaults
"curly": true,
"eqnull": true,
"eqeqeq": true,
"undef": true,
globals: {
jQuery: true,
console: true,
module: 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('test', ['jshint']);
grunt.registerTask('default', ['jshint', 'concat', 'uglify']);
};
0 files lint free does not mean that you have files which have errors, it means that zero files are checked!
the jshint-task will output errors to your console (including file, linenumber and column)
thats where you specify your files to check:
files: ['gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
if you change 'gruntfile.js' to 'Gruntfile.js' (case sensitive!) it should check your gruntfile (which you of course already have).

Resources